AtomicIntegerFieldUpdater源码解析
AtomicIntegerFieldUpdater类介绍
AtomicIntegerFieldUpdater类是JDK提供的volatile int封装器。可以通过它来原子更新某些对象的volatile修饰的int字段。
看下面这个例子,假设NotUseAtomicIntegerFieldUpdate类有一个字段value,它在某些场景下需要具有原子更新的能力,但又不能使用AtomicInteger(可以认为是出于节省空间的考虑)。这个时候,AtomicIntegerFieldUpdater就派上用场了。
1 | public class NotUseAtomicIntegerFieldUpdate implements Runnable { |
类图
主要属性
无。主要属性在AtomicIntegerFieldUpdaterImpl中。这里就拿AtomicIntegerFieldUpdaterImpl的属性来说明
1 | private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); |
U: Unsafe类,实现CAS算法
offset:Field字段在整个AtomicIntegerFieldUpdaterImpl中的内存偏移。
cclass:如果字段受保护,cclass为调用者类的Class对象,否则cclass等于tclass
tclass:被操作对象类的Class对象
主要方法
newUpdater(Class, String)
1 | public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, |
静态方法,创建一个AtomicIntegerFieldUpdater对象。
AtomicIntegerFieldUpdater()
1 | /** |
受限的构造函数,不做什么。
compareAndSet(T,int,int)
1 | public abstract boolean compareAndSet(T obj, int expect, int update); |
抽象方法,在AtomicIntegerFieldUpdaterImpl中实现
weakCompareAndSet(T,int,int)
1 | public abstract boolean weakCompareAndSet(T obj, int expect, int update); |
抽象方法,在AtomicIntegerFieldUpdaterImpl中实现
set(T, int)
1 | public abstract void set(T obj, int newValue); |
抽象方法,在AtomicIntegerFieldUpdaterImpl中实现
lazySet(T,int)
1 | public abstract void lazySet(T obj, int newValue); |
抽象方法,在AtomicIntegerFieldUpdaterImpl中实现
get(T)
1 | public abstract int get(T obj); |
抽象方法,在AtomicIntegerFieldUpdaterImpl中实现
getAndSet(T,int)
1 | /** |
返回当前值,并将当前值设置为newValue。这里是一个死循环,极端情况下,可能导致自旋过久。
getAndIncrement(T)
1 | /** |
返回当前值,并将当前值加上1.此处是一个死循环处理,极端情况下可能会自旋过久,
getAndDecrement(T)
1 | /** |
返回当前值,并将当前值减去1。此处是一个死循环处理,极端情况下可能会自旋过久。
getAndAdd(T, int)
1 | /** |
返回当前值,并将当前值加上delta。此处是一个死循环处理,极端情况下可能会自旋过久。
incrementAndGet(T)
1 | /** |
将当前的值自增1,并返回。此处是一个死循环处理,极端情况下可能会自旋过久。
decrementAndGet(T)
1 | /** |
将当前的值自减1,并返回。此处是一个死循环处理,极端情况下可能会自旋过久。
addAndGet(T,int)
1 | /** |
将当前值加上delta,并返回。此处是一个死循环处理,极端情况下可能会自旋过久。
getAndUpdate(T,IntUnaryOperator)
1 | /** |
获取当前值,并将当前值应用单元函数updateFunction,并更新当前值。此处是一个死循环处理,极端情况下可能会自旋过久。
updateAndGet(T,IntUnaryOperator)
1 | /** |
将当前值应用于单元函数updateFunction,并更新当前值,返回最新的当前值。此处是一个死循环处理,极端情况下可能会自旋过久。
getAndAccumulate(T,int,IntBinaryOperator)
1 | /** |
返回当前值。并将当前值和x应用于二元函数accumulateFunction,更新当前值。此处是一个死循环处理,极端情况下可能会自旋过久。
accumulateAndGet(T,int,IntBinaryOperator)
1 | /** |
将当前值和x应用于二元函数accumulatorFunction,并将结果更新于当前值,返回。此处是一个死循环处理,极端情况下可能会自旋过久。
AtomicIntegerFieldUpdaterImpl#UpdaterImpl(Class,String,Class)
1 | AtomicIntegerFieldUpdaterImpl(final Class<T> tclass, |
从上述代码中可以看到,如果字段想要被AtomicIntegerFieldUpdater修改的话,必须要满足下面几个条件:
- 字段必须是volatile类型的,在线程之间共享变量时保证立即可见.eg:volatile int value = 3
- 字段的描述类型(修饰符public/protected/default/private)是与调用者与操作对象字段的关系一致。也就是说调用者能够直接操作对象字段,那么就可以反射进行原子操作。但是对于父类的字段,子类是不能直接操作的,尽管子类可以访问父类的字段。
- 只能是实例变量,不能是类变量,也就是说不能加static关键字。
- 只能是可修改变量,不能使final变量,因为final的语义就是不可修改。实际上final的语义和volatile是有冲突的,这两个关键字不能同时存在。
- 对于AtomicIntegerFieldUpdater和AtomicLongFieldUpdater只能修改int/long类型的字段,不能修改其包装类型(Integer/Long)。如果要修改包装类型就需要使用AtomicReferenceFieldUpdater。
AtomicIntegerFieldUpdaterImpl#isAncestor(ClassLoader, ClassLoader)
1 | /** |
如果第二个加载器能在第一个加载器的加载链路上找到,返回true,否则false
AtomicIntegerFieldUpdaterImpl#isSamePackage(Class, Class)
1 | /** |
判断两个类是否是同一个类加载器加载的并且同属于一个包
AtomicIntegerFieldUpdaterImpl#getPackageName(Class)
1 | private static String getPackageName(Class<?> cls) { |
返回类的包名
AtomicIntegerFieldUpdaterImpl#accessCheck(T)
1 | /** |
判断对象obj是否是cclass的实例,不是的话抛出AccessCheckException
AtomicIntegerFieldUpdaterImpl#throwAccessCheckException(T)
1 | /** |
如果访问检查失败或者Class转换失败,抛出异常。
AtomicIntegerFieldUpdaterImpl#compareAndSet(T,int,int)
1 | public final boolean compareAndSet(T obj, int expect, int update) { |
如果当前值等于期望值except,就把当前值设置为update,返回true,否则返回false。
AtomicIntegerFieldUpdaterImpl#weakCompareAndSet(T,int,int)
1 | public final boolean weakCompareAndSet(T obj, int expect, int update) { |
从父类的注释上看,这个方法的本意是,调用weakCompareAndSet方法时不能保证指令重排的发生,因此,这个方法有时候会毫无理由地失败。
AtomicIntegerFieldUpdaterImpl#set(T,int)
1 | public final void set(T obj, int newValue) { |
将对象obj的fieldName字段设置为newValue
AtomicIntegerFieldUpdaterImpl#lazySet(T, int)
1 | public final void lazySet(T obj, int newValue) { |
该方法是“慢慢”地将对象的obj的fieldName字段设置为newValue。这就意味着有段时间,多线程环境下,会有线程读取到旧值。
AtomicIntegerFieldUpdaterImpl#get(T)
1 | public final int get(T obj) { |
获取对象obj的fieldName字段的值
AtomicIntegerFieldUpdaterImpl#getAndSet(T,int)
1 | public final int getAndSet(T obj, int newValue) { |
返回当前值,并将当前值设置为newValue
AtomicIntegerFieldUpdaterImpl#getAndAdd(T,int)
1 | public final int getAndAdd(T obj, int delta) { |
返回当前值,并将当前值加上delta,更新。
AtomicIntegerFieldUpdaterImpl#getAndIncrement(T)
1 | public final int getAndIncrement(T obj) { |
返回当前值,并将当前值加上1,更新当前值
AtomicIntegerFieldUpdaterImpl#getAndDecrement(T)
1 | public final int getAndDecrement(T obj) { |
返回当前值,并将当前值减1,更新当前值。
AtomicIntegerFieldUpdaterImpl#incrementAndGet(T)
1 | public final int incrementAndGet(T obj) { |
将当前值加1,并更新,返回当前值。
AtomicIntegerFieldUpdaterImpl#decrementAndGet(T)
1 | public final int decrementAndGet(T obj) { |
将当前值加减1,并更新,返回当前值。
AtomicIntegerFieldUpdaterImpl#addAndGet(T,int)
1 | public final int addAndGet(T obj, int delta) { |
将当前值加上delta,更新,并返回更新后的当前值。
应用
我们将上面的代码改写下,用一个静态的AtomicIntegerFieldUpdater对象来持有value字段,进行原子更新。
1 | public class NotUseAtomicIntegerFieldUpdate { |
现在无论再怎么运行,结果都是一致的了。