atomicreference 是基于 cas 实现的线程安全引用容器,通过 volatile 变量和 unsafe 提供的硬件级原子操作保证无锁更新;核心方法包括 compareandset、getandset 等,适用于无锁栈、计数器等场景,但需注意 aba 问题及对象内部状态非自动线程安全。

AtomicReference 是 Java 并发包(java.util.concurrent.atomic)中提供的一个线程安全的引用容器,它通过底层 CPU 的 CAS(Compare-And-Swap)指令实现无锁(lock-free)的对象引用更新,避免了 synchronized 或显式锁带来的开销和阻塞。
核心原理:CAS 保证原子性
AtomicReference 内部维护一个 volatile 引用变量,并借助 Unsafe 类调用硬件级 CAS 指令。每次更新前,先检查当前值是否等于预期值(expected),相等才替换为新值(update);否则失败并可重试。整个过程不加锁、不阻塞线程。
关键方法:
-
compareAndSet(expected, update):原子比较并设置,成功返回 true -
getAndSet(newValue):获取旧值并设置新值(原子) -
get()和set(newValue):分别等价于 volatile 读/写(可见性保障)
典型使用场景:无锁栈或计数器状态管理
比如实现一个简单的无锁栈(LIFO)节点引用更新:
public class LockFreeStack<e> {
private AtomicReference<node>> top = new AtomicReference();
public void push(E item) {
Node<e> newNode = new Node(item);
Node<e> currentTop;
do {
currentTop = top.get();
newNode.next = currentTop;
} while (!top.compareAndSet(currentTop, newNode));
}
public E pop() {
Node<e> currentTop;
Node<e> newTop;
do {
currentTop = top.get();
if (currentTop == null) return null;
newTop = currentTop.next;
} while (!top.compareAndSet(currentTop, newTop));
return currentTop.item;
}
private static class Node<e> {
final E item;
volatile Node<e> next;
Node(E item) { this.item = item; }
}
}</e></e></e></e></e></e></node></e>
注意:这里必须用 volatile Node<e> next</e> 配合 CAS,确保多线程下链表结构可见且更新有序。
进阶技巧:带版本号的 ABA 问题规避
CAS 存在 ABA 问题(值从 A→B→A,CAS 误判为未变)。若业务敏感,可用 AtomicStampedReference 或 AtomicMarkableReference 增加版本戳或标记位。
例如:
AtomicStampedReference<string> ref = new AtomicStampedReference("init", 0);</string>-
ref.compareAndSet(oldVal, newVal, expectedStamp, newStamp)同时校验值和版本号
注意事项与常见误区
使用 AtomicReference 时需注意:
- 只保证引用本身原子,**不保证对象内部状态线程安全**(如更新对象字段仍需同步)
- 避免长时间自旋重试(如高竞争下 compareAndSet 反复失败),可结合退避策略或改用更高级并发结构(如 ConcurrentLinkedQueue)
- 不能用于非原子操作组合(如“先 get 再 set”不是原子的,必须用 compareAndSet 循环实现)
- 初始化值建议明确指定,避免 null 引发 NPE(尤其 compareAndSet 中传 null 要小心)
只要理解 CAS 语义、合理设计状态转换逻辑,AtomicReference 就能高效支撑多数无锁数据结构的构建。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











