AtomicReferenceFieldUpdater源码解析
AtomicReferenceFieldUpdater类介绍
AtomicReferenceFieldUpdater是Doug Lea在Java 5中写的atomic classes 中Filed Updater的一部分,本质上是volatile字段的包装器。
AtomicReferenceFieldUpdater是基于反射的工具类,用来将指定类型的指定的volatile引用字段进行原子更新,对应的原子引用字段不能是private的。通常一个类volatile成员属性获取值、设定为某个值两个操作时非原子的,若想将其变为原子的,则可通过AtomicReferenceFieldUpdater来实现。
类图
主要属性
AtomicReferenceFieldUpdater本身是没有属性的,但是我们可以通过它的继承类来一窥究竟。
1 | private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); |
U:JDK提供的底层实现CAS算法的类
cclass:待更新的的对象的类的Class对象
tclass:待操作的目标对象
vclass:待操作的字段的类型
主要方法
newUpdater(Class, Class vclass, String)
创建一个新的原子更新器
1 | /** |
AtomicReferenceFieldUpdater()
1 | /** |
compareAndSet(T,V,V)
抽象方法,具体实现看实现类
weakCompareAndSet(T,V,V)
抽象方法,具体实现看实现类
set(T,V)
抽象方法,具体实现看实现类
lazySet(T,V)
抽象方法,具体实现看实现类
get(T):V
抽象方法,具体实现看实现类
getAndSet(T,V)
1 | /** |
返回当前的值,并将当前值设置为新值newValue。需要注意的是,此处使用的是一个死循环,在极端的多线程环境下,这个循环可能要运行很久。
getAndUpdate(T,UnaryOperator)
1 | /** |
获取当前值,返回。然后将当前值应用于单元函数,并将结果更新到当前值上。需要注意的是,此处使用的是一个死循环,在极端的多线程环境下,这个循环可能要运行很久。
updateAndGet
1 | /** |
将当前值应用于单元函数,并将获得的结果更新至当前值,返回。需要注意的是,此处使用的是一个死循环,在极端的多线程环境下,这个循环可能要运行很久。
getAndAccumulate(T,V,BinaryOperator)
1 | /** |
获取当前值,返回。并将当前值和x应用于双元函数,将获得的结果更新当前值。需要注意的是,此处使用的是一个死循环,在极端的多线程环境下,这个循环可能要运行很久。
accumulateAndGet(T,V,BinaryOperator)
1 | /** |
将当前值和x应用于双元函数,并将结果更新值当前值,返回。需要注意的是,此处使用的是一个死循环,在极端的多线程环境下,这个循环可能要运行很久。
AtomicReferenceFieldUpdaterImpl(Class, Class, String, Class)
1 | /* |
生成AtomicReferenceFieldUpdater对象。
原子更新器的使用存在比较苛刻的条件如下
- 操作的字段不能是static类型。
- 操作的字段不能是final类型的,因为final根本没法修改。
- 字段必须是volatile修饰的,也就是数据本身是读一致的。
- 属性必须对当前的Updater所在的区域是可见的,如果不是当前类内部进行原子更新器操作不能使用private,protected子类操作父类时修饰符必须是protect权限及以上,如果在同一个package下则必须是default权限及以上,也就是说无论何时都应该保证操作类与被操作类间的可见性。
isAncestor(ClassLoader, ClassLoader)
1 | /** |
判断两个classes是否是相同的类加载器和包修饰
isSamePackage(Class, Class)
1 | /** |
判断两个类是否具有相同的包名
getPackageName(Class)
1 | private static String getPackageName(Class<?> cls) { |
获取类的包名称
accessCheck(T)
1 | /** |
确认目标对象obj是cclass的实例。
throwAccessCheckException(T)
1 | /** |
如果待持有的字段受保护或者类型转换失败,抛出异常
valueCheck(V)
1 | private final void valueCheck(V v) { |
校验v是否是vclass的实例
throwCCE()
1 | static void throwCCE() { |
抛出ClassCaseException异常
compareAndSet(T,V,V)
1 | public final boolean compareAndSet(T obj, V expect, V update) { |
先校验obj是否是T的实例,再校验update是否是V 的实例。
然后再当前值等同于except时,将当前值更新为update,并返回true,否则返回false。
weakCompareAndSet(T,V,V)
1 | public final boolean weakCompareAndSet(T obj, V expect, V update) { |
实现同compareAndSet
set(T,V)
1 | public final void set(T obj, V newValue) { |
先校验obj是否是T的实例,再校验update是否是V 的实例。最后再设置当前值为newValue。
lazySet(T,V)
1 | public final void lazySet(T obj, V newValue) { |
先校验obj是否是T的实例,再校验update是否是V 的实例。最后在“慢慢”把当前值设置为newValue。这里“慢慢”表示,在多线程环境下,会有一段时间,其他线程还是能读取到旧值的。
get(T)
1 |
|
先校验obj是否是T的实例,再返回对应的值。
getAndSet(T,V)
1 | @SuppressWarnings("unchecked") |
先校验obj是否是T的实例,再校验update是否是V 的实例。最后返回当前值,并把当前值设置为newValue。
应用
看下面这个例子
1 | public class AtomicReferTest { |
输出结果
1 | true |