并发编程 — AtomicXXXFieldUpdater 详解

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 类的使用方式很简单,只需要以下几步:

  1. 通过   AtomicXXXFieldUpdater 类的 newUpdater方法构建,在构造时传入class对象和需要原子更新的属性名。
  2. 创建一个 实例对象
  3. 通过原子操作 更新对应的属性。

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、父类的成员属性无法被原子性地更新

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值