Java多线程系列--“JUC原子类”03之 AtomicLongArray原子类

2021年11月21日 阅读数:12
这篇文章主要向大家介绍Java多线程系列--“JUC原子类”03之 AtomicLongArray原子类,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

 

概要

AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray这3个数组类型的原子类的原理和用法类似。本章以AtomicLongArray对数组类型的原子类进行介绍。内容包括:java

​AtomicLongArray介绍和函数列表​数组

​AtomicLongArray源码分析(基于JDK1.7.0_40)​多线程

​AtomicLongArray示例​ide

 

AtomicLongArray介绍和函数列表

在"​​Java多线程系列--“JUC原子类”02之 AtomicLong原子类​​"中介绍过,AtomicLong是做用是对长整形进行原子操做。而AtomicLongArray的做用则是对"长整形数组"进行原子操做。函数

 

AtomicLongArray函数列表源码分析



Java多线程系列--“JUC原子类”03之 AtomicLongArray原子类_原子类

// 建立给定长度的新 AtomicLongArray。
AtomicLongArray(int length)
// 建立与给定数组具备相同长度的新 AtomicLongArray,并从给定数组复制其全部元素。
AtomicLongArray(long[] array)

// 以原子方式将给定值添加到索引 i 的元素。
long addAndGet(int i, long delta)
// 若是当前值 == 预期值,则以原子方式将该值设置为给定的更新值。
boolean compareAndSet(int i, long expect, long update)
// 以原子方式将索引 i 的元素减1。
long decrementAndGet(int i)
// 获取位置 i 的当前值。
long get(int i)
// 以原子方式将给定值与索引 i 的元素相加。
long getAndAdd(int i, long delta)
// 以原子方式将索引 i 的元素减 1。
long getAndDecrement(int i)
// 以原子方式将索引 i 的元素加 1。
long getAndIncrement(int i)
// 以原子方式将位置 i 的元素设置为给定值,并返回旧值。
long getAndSet(int i, long newValue)
// 以原子方式将索引 i 的元素加1。
long incrementAndGet(int i)
// 最终将位置 i 的元素设置为给定值。
void lazySet(int i, long newValue)
// 返回该数组的长度。
int length()
// 将位置 i 的元素设置为给定值。
void set(int i, long newValue)
// 返回数组当前值的字符串表示形式。
String toString()
// 若是当前值 == 预期值,则以原子方式将该值设置为给定的更新值。
boolean weakCompareAndSet(int i, long expect, long update)


Java多线程系列--“JUC原子类”03之 AtomicLongArray原子类_原子类


 

AtomicLongArray源码分析(基于JDK1.7.0_40)

AtomicLongArray的完整源码atom


Java多线程系列--“JUC原子类”03之 AtomicLongArray原子类_juc_03 View Code spa


 

AtomicLongArray的代码很简单,下面仅以incrementAndGet()为例,对AtomicLong的原理进行说明。线程

incrementAndGet()源码以下:code



public final long incrementAndGet(int i) {
return addAndGet(i, 1);
}


说明:incrementAndGet()的做用是以原子方式将long数组的索引 i 的元素加1,并返回加1以后的值。

 

addAndGet()源码以下:



Java多线程系列--“JUC原子类”03之 AtomicLongArray原子类_原子类

public long addAndGet(int i, long delta) {
// 检查数组是否越界
long offset = checkedByteOffset(i);
while (true) {
// 获取long型数组的索引 offset 的原始值
long current = getRaw(offset);
// 修改long型值
long next = current + delta;
// 经过CAS更新long型数组的索引 offset的值。
if (compareAndSetRaw(offset, current, next))
return next;
}
}


Java多线程系列--“JUC原子类”03之 AtomicLongArray原子类_原子类


说明:addAndGet()首先检查数组是否越界。若是没有越界的话,则先获取数组索引i的值;而后经过CAS函数更新i的值。

 

getRaw()源码以下:



private long getRaw(long offset) {
return unsafe.getLongVolatile(array, offset);
}


说明:unsafe是经过Unsafe.getUnsafe()返回的一个Unsafe对象。经过Unsafe的CAS函数对long型数组的元素进行原子操做。如compareAndSetRaw()就是调用Unsafe的CAS函数,它的源码以下:



private boolean compareAndSetRaw(long offset, long expect, long update) {
return unsafe.compareAndSwapLong(array, offset, expect, update);
}


 

AtomicLongArray示例



Java多线程系列--“JUC原子类”03之 AtomicLongArray原子类_原子类

1 // LongArrayTest.java的源码
2 import java.util.concurrent.atomic.AtomicLongArray;
3
4 public class LongArrayTest {
5
6 public static void main(String[] args){
7
8 // 新建AtomicLongArray对象
9 long[] arrLong = new long[] {10, 20, 30, 40, 50};
10 AtomicLongArray ala = new AtomicLongArray(arrLong);
11
12 ala.set(0, 100);
13 for (int i=0, len=ala.length(); i<len; i++)
14 System.out.printf("get(%d) : %s\n", i, ala.get(i));
15
16 System.out.printf("%20s : %s\n", "getAndDecrement(0)", ala.getAndDecrement(0));
17 System.out.printf("%20s : %s\n", "decrementAndGet(1)", ala.decrementAndGet(1));
18 System.out.printf("%20s : %s\n", "getAndIncrement(2)", ala.getAndIncrement(2));
19 System.out.printf("%20s : %s\n", "incrementAndGet(3)", ala.incrementAndGet(3));
20
21 System.out.printf("%20s : %s\n", "addAndGet(100)", ala.addAndGet(0, 100));
22 System.out.printf("%20s : %s\n", "getAndAdd(100)", ala.getAndAdd(1, 100));
23
24 System.out.printf("%20s : %s\n", "compareAndSet()", ala.compareAndSet(2, 31, 1000));
25 System.out.printf("%20s : %s\n", "get(2)", ala.get(2));
26 }
27 }


Java多线程系列--“JUC原子类”03之 AtomicLongArray原子类_原子类


运行结果



Java多线程系列--“JUC原子类”03之 AtomicLongArray原子类_原子类

get(0) : 100
get(1) : 20
get(2) : 30
get(3) : 40
get(4) : 50
getAndDecrement(0) : 100
decrementAndGet(1) : 19
getAndIncrement(2) : 30
incrementAndGet(3) : 41
addAndGet(100) : 199
getAndAdd(100) : 19
compareAndSet() : true
get(2) : 1000