AtomicReference如何保证对象在共享变量的原子操作?
AtomicReference 属于 Java 并发包下面的一个原子操作类,其可以原子更新引用类型。示例代码如下所示:
AtomicReference<User> atomicUserRef = new AtomicReference<User>();
User user = new User("Tom");
atomicUserRef.set(user);
User updateUser = new User("Lili");
// 原子更新引用类型
atomicUserRef.compareAndSet(user, updateUser);
AtomicReference 在多线程环境下,能够做到原子更新引用类型主要由以下两个原因:
一、在 AtomicReference 内部定义了一个 volatile 类型的引用,用于存储当前引用类型:
private volatile V value;
volatile 能够保证 A 线程更新了 value 值后,B 线程能即时看到。即可见性。
二、compareAndSet 借助的是 unsafe 类进行更新的:
public final boolean compareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
Unsafe 类最终调用的是 C++ 方法,C++ 最终调用的是处理器提供的用于原子更新的 CAS (Compare And Swap) 指令。当前绝大多数处理器都已经实现了这个指令,所以原子更新是需要底层处理器指令支持的。
原子引用保证同一时间只能获取一个句柄,当句柄被占用,其它申请操作将阻塞。其前缀“Atomic”其实是强调句柄的申请和分配是原子安全且高效的,高效是因为底层使用(正常情况下)原子指令来完成句柄的锁定操作,而非互斥体(Mutex)。原子操作是特定CPU指令支持,不需要操作系统分配内核资源,所以极其高效。