AtomicXXXFieldUpdater 其中包含 AtomicIntegerFieldUpdater、AtomicLongFieldUpdater 和AtomicReferenceFieldUpdater 三个类。
1、为什么需要 AtomicXXXFieldUpdater
如果一个类是自己编写的,则可以在编写的时候把成员变量定义为Atomic类型。但如果是一个已经有的类,在不能更改其源代码的情况下,要想实现对其成员变量的原子操作,就需要AtomicIntegerFieldUpdater、AtomicLongFieldUpdater 和 AtomicReferenceFieldUpdater。
下面以AtomicIntegerFieldUpdater为例介绍其实现原理。
2、使用方法
public class AtomicFieldUpdaterExample {
// 定义一个类
static class Account{
// balance 不具备原子性操作
volatile int balance;
public int getBalance() {
return balance;
}
}
public static void main(String[] args) {
// 定义 AtomicIntegerFieldUpdater 通过 newUpdater 方法构建 AtomicIntegerFieldUpdater
AtomicIntegerFieldUpdater<Account> aifu =
AtomicIntegerFieldUpdater.newUpdater(Account.class, "balance");
// 实例化一个 account 对象
Account account = new Account();
// 原子性的操作 balance 属性
aifu.compareAndSet(account, 0, 10);
System.out.println("获取当前值:" + account.getBalance());
}
}
通过上面实例我们发现 AtomicXXXFieldUpdater 类的使用方式很简单,只需要以下几步:
- 通过 AtomicXXXFieldUpdater 类的 newUpdater方法构建,在构造时传入class对象和需要原子更新的属性名。
- 创建一个 实例对象
- 通过原子操作 更新对应的属性。
3、源码分析
3.1、newUpdater 方法
//静态方法,传传入的是要修改的类(不是对象)和 对应的成员变量的
public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass,
String fieldName) {
return new AtomicIntegerFieldUpdaterImpl<U>
(tclass, fieldName, Reflection.getCallerClass());
}
这个方法 是一个静态方法,内部实现也很简单,就是创建了一个 AtomicIntegerFieldUpdater 实现类 AtomicIntegerFieldUpdaterImpl 对象。
3.2、AtomicIntegerFieldUpdaterImpl 类
成员变量
// 成员变量unsafe是原子变量相关操作的基础
// 原子变量的修改操作最终有sun.misc.Unsafe类的CAS操作实现
private static final Unsafe unsafe = Unsafe.getUnsafe();
// 成员变量fieldName的内存偏移值,在构造函数中初始化
private final long offset;
// 操作目标类,对该类中的fieldName字段进行更新
private final Class<T> tclass;
// 调用者类,通过反射获取
private final Class cclass;
构造函数
AtomicIntegerFieldUpdaterImpl(Class<T> tclass, String fieldName, Class<?> caller) {
Field field = null;
int modifiers = 0;
try {
// 获取要更新的类的指定成员变量fieldName的访问策略
field = tclass.getDeclaredField(fieldName);
modifiers = field.getModifiers();
// 验证访问策略
sun.reflect.misc.ReflectUtil.ensureMemberAccess(
caller, tclass, null, modifiers);
sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
// 当前成员变量的类型必须是int
Class fieldt = field.getType();
if (fieldt != int.class)
throw new IllegalArgumentException("Must be integer type");
// 当前成员变量必须是volatile修饰
if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type");
// 设置调用者类
this.cclass = (Modifier.isProtected(modifiers) &&
caller != tclass) ? caller : null;
// 设置目标操作类
this.tclass = tclass;
// 设置成员变量的内存偏移值
offset = unsafe.objectFieldOffset(field);
}
4、注意事项
1、未被volatile关键字修饰的成员属性无法被原子性地更新
2、类变量无法被原子性地更新
3、无法直接访问的成员属性不支持原子性地更新
4、final修饰的成员属性无法被原子性地更新
5、父类的成员属性无法被原子性地更新