AtomicReference 是基于 CAS 实现的无锁线程安全引用类,支持原子读取、设置和条件更新;适用于共享引用的安全更新、无锁数据结构构建及函数式原子操作,但不保证对象内部线程安全,需注意 ABA 问题与性能陷阱。

AtomicReference 是 Java 并发包(java.util.concurrent.atomic)中用于实现对象引用**无锁、线程安全更新**的核心原子类。它不依赖 synchronized 或 Lock,而是基于底层 CAS(Compare-And-Swap)指令,保证对引用的读取、比较并设置操作是原子的。
核心用途:安全地更新共享对象引用
当你有多个线程需要共同维护一个对象引用(比如配置、状态、单例实例、链表节点等),且希望更新时满足“先检查再修改”的逻辑(如:仅当当前值为 A 时才设为 B),AtomicReference 就是最直接的选择。它避免了加锁带来的阻塞和开销,也规避了 volatile 无法保障复合操作原子性的缺陷。
基本用法:创建、读取、设置、CAS 更新
以一个简单的开关状态为例(用 Boolean 封装):
AtomicReference<Boolean> flag = new AtomicReference<>(false); // ✅ 安全读取当前值 boolean current = flag.get(); // 返回 false // ✅ 无条件设置新值(原子写) flag.set(true); // ✅ 条件更新:仅当当前值为 false 时,才设为 true boolean updated = flag.compareAndSet(false, true); // 返回 true,成功 // ✅ 获取旧值并设为新值(原子交换) Boolean old = flag.getAndSet(false); // old = true,flag 变为 false
典型场景:实现无锁栈或状态机
AtomicReference 常用于构建更高级的无锁数据结构。例如,实现一个简易的线程安全栈节点:
立即学习“Java免费学习笔记(深入)”;
class Node<T> {
final T value;
Node<T> next;
Node(T value) { this.value = value; }
}
class LockFreeStack<T> {
private AtomicReference<Node<T>> top = new AtomicReference<>();
public void push(T item) {
Node<T> newNode = new Node<>(item);
Node<T> currentTop;
do {
currentTop = top.get();
newNode.next = currentTop;
} while (!top.compareAndSet(currentTop, newNode)); // CAS 失败则重试
}
public T pop() {
Node<T> currentTop;
Node<T> newTop;
do {
currentTop = top.get();
if (currentTop == null) return null;
newTop = currentTop.next;
} while (!top.compareAndSet(currentTop, newTop));
return currentTop.value;
}
}
这里关键点是:所有修改都基于 compareAndSet 的循环重试(自旋)策略,确保在多线程竞争下最终达成一致状态。
进阶技巧:使用 updateAndGet / getAndUpdate(JDK 8+)
如果更新逻辑较复杂(比如根据旧值计算新值),可用函数式方法避免手动循环:
AtomicReference<Integer> counter = new AtomicReference<>(0); // 原子地 +1,并返回新值 int newValue = counter.updateAndGet(i -> i + 1); // 返回 1 // 原子地 +1,并返回旧值 int oldValue = counter.getAndUpdate(i -> i + 1); // 返回 1,内部变为 2 // 更灵活:只在满足条件时更新(类似 CAS 的语义封装) counter.accumulateAndGet(5, Integer::max); // 设为 max(当前值, 5)
这些方法内部仍基于 CAS 实现,但封装了重试逻辑,代码更简洁、意图更清晰。
注意事项与常见误区
- 只保证引用本身原子,不保证对象内部线程安全:AtomicReference<List> 能安全替换整个 List 对象,但若多个线程同时调用 list.add(),仍需同步 —— 引用原子 ≠ 内容原子。
- CAS 存在 ABA 问题:若引用从 A → B → A,compareAndSet 会误认为未变而成功。如需严格校验变化历史,应使用 AtomicStampedReference(带版本戳)或 AtomicMarkableReference(带标记位)。
- 慎用 long、double 等大对象引用:虽然语法允许,但频繁创建包装对象可能引发 GC 压力;高频更新建议优先考虑 AtomicLong 等专用数值类。
- 避免在 lambda 中做耗时操作:updateAndGet 等函数式方法会在 CAS 循环内执行,若计算耗时,会拉长自旋时间,影响性能甚至导致饥饿。


















