AtomicReferenceArray源码解析
AtomicReferenceArray类介绍
java.util.concurrent.atomic.AtomicReferenceArray类提供了可以原子读取和写入的底层引用数组的操作,并且还包含高级原子操作。 AtomicReferenceArray支持对底层引用数组变量的原子操作。 它具有获取和设置方法,如在变量上的读取和写入。 也就是说,一个集合与同一变量上的任何后续获取相关联。 原子compareAndSet方法也具有这些内存一致性功能。
类图
主要属性
1 | private static final Unsafe unsafe; |
unsafe:Unsafe,JDK提供的实现CAS算法的类
base:数组中第一个元素的内存地址
shift:左移偏移量。基于对象的数组,shift是根据不同对象来决定不同值的用来计算,数组中的元素在整个AtomicReferenceArray对象中的偏移量。数组中第i个元素的地址就是 i << shift + base.
arrayFieldOffset: array 相对于对象的偏移量
上述三个字段会在静态代码块中完成初始化
1 | static { |
toString():存放元素的数组
主要方法
checkedByteOffset(int)
1 | private long checkedByteOffset(int i) { |
检验索引是否越界,并返回对应位置的偏移量
byteOffset(int)
1 | private static long byteOffset(int i) { |
返回对应索引的偏移量
AtomicReferenceArray(int)
1 | /** |
创建指定长度的原子引用数组
AtomicReferenceArray(E[])
1 | /** |
根据给定的数组,创建相同长度的原子引用数组。
length()
1 | /** |
返回当前数组的长度
get(int)
1 | /** |
返回指定索引上的值
getRaw(long)
1 |
|
调用unsafe,获取指定位移上的值
set(int, E)
1 | /** |
将指定位置上的值设置为newValue
lazySet(int,E)
1 | /** |
调用unsafe的方法直接将位置i上的值设置为给定的新值。但是这个方法有别于上面的set方法,它在一段时间内是有可能让其他线程查到原来的旧值,而不是立马查到新值。因此,它可以算是一个“最终一致性”的方法
getAndSet(int,E)
1 | /** |
获取当前值,返回,并将当前值设置为newValue
compareAndSet(int,E,E)
1 | /** |
如果位置i上的值等同于except,那就将该值更新为update,并返回true,否则返回false。
compareAndSetRaw(long,E,E)
1 | private boolean compareAndSetRaw(long offset, E expect, E update) { |
如果指定偏移量处的值等同于except,那就将该值更新为update,并返回true,否则返回false。
weakCompareAndSet(int, E,E)
1 | /** |
这个方法的本意是,调用weakCompareAndSet方法时不能保证指令重排的发生,因此,这个方法有时候会毫无理由地失败。
但是从实现上来看,这个方法还是和compareAndSet一模一样的。不过建议在使用的时候,谨慎对待,保不定什么时候,方法实现就修改了。
getAndUpdate(int,UnaryOperator)
1 | /** |
获取位置i上的值,并将该值应用于单元函数updateFunction,并将其结果更新于当前值。需要注意的是,此处使用的是一个循环,如果一直更新不成功的话,线程会一直自旋在此处。
updateAndGet(int, UnaryOperator)
1 | /** |
将当前值应用单元函数,并将获得的值更新当前值,返回。需要注意的是,此处使用的是一个循环,如果一直更新不成功的话,线程会一直自旋在此处。
getAndAccumulate(int,E,BinaryOperator)
1 | /** |
返回当前值。并将x和当前值应用于双元函数,将其结果更新值当前值上。需要注意的是,此处使用的是一个循环,如果一直更新不成功的话,线程会一直自旋在此处。
accumulateAndGet(int,E,BinaryOperator)
1 | /** |
将x和当前值应用于双元函数,并将其结果更新至当前值,返回。需要注意的是,此处使用的是一个循环,如果一直更新不成功的话,线程会一直自旋在此处。
toString()
1 | /** |
返回当前数组的字符串形式
readObject(ObjectInputStream)
1 | /** |
从输入流中读取数据并构造数组。