AtomicReference 通过 CAS 和 volatile 实现引用的原子更新与可见性,仅保障引用地址的线程安全,不保证对象内部状态安全;支持 compareAndSet 等操作,并可通过 AtomicStampedReference 解决 ABA 问题。

AtomicReference 通过 CAS(Compare-And-Swap)机制实现对象的原子更新,不依赖锁,保证多线程下引用赋值的原子性与可见性。
核心原理:CAS 操作
AtomicReference 内部持有一个 volatile 修饰的引用变量,并借助 Unsafe 类的 compareAndSwapObject 方法完成原子更新:
- CAS 会先比较当前引用值是否等于预期值(expected),相等则将引用更新为新值(update),返回 true;否则不修改,返回 false
- 整个比较+替换过程由 CPU 硬件指令保证原子性(如 x86 的 cmpxchg)
- volatile 保证了引用值的写操作对其他线程立即可见,避免指令重排序
基本用法示例
常见操作包括 get、set、compareAndSet、getAndSet 等:
-
get():获取当前引用值(带 volatile 读语义) -
set(newValue):设置新引用(带 volatile 写语义) -
compareAndSet(expected, update):原子地尝试更新,成功返回 true -
getAndSet(newValue):原子地设置新值并返回旧值
例如实现一个线程安全的计数器包装类:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
AtomicReference<Integer> counter = new AtomicReference<>(0);counter.compareAndSet(5, 6); // 若当前是 5,则设为 6
注意对象本身不可变 ≠ 原子性保障
AtomicReference 只保证“引用地址”的原子更新,不保证其指向对象内部状态的线程安全:
- 如果对象是可变的(比如普通 Person 对象),多个线程同时调用 person.setName() 仍需额外同步
- 若需整体状态原子更新,应配合使用不可变对象(如 final 字段 + 无 setter),或采用 AtomicReferenceFieldUpdater / 更高阶的 stamped lock 等方案
- 也可用 AtomicReference 存储新构建的对象(如每次更新都 new 一个新实例),实现乐观并发控制
进阶:带版本号的原子更新(ABA 问题应对)
普通 CAS 无法识别 A→B→A 场景(即引用值从 A 变成 B 又变回 A),可能引发逻辑错误。Java 提供了 AtomicStampedReference 和 AtomicMarkableReference 来附加版本号或标记位:
-
AtomicStampedReference将引用和整型戳(stamp)打包成 pair,CAS 同时校验二者 - 适用于需要严格顺序判断的场景,如无锁栈、队列中的节点回收

















