atomicreference 是 java 中基于 cas 实现无锁线程安全引用更新的核心类,通过 volatile 保证可见性,支持 compareandset 等原子操作,但需注意 aba 问题和引用相等性默认用 == 判断。

AtomicReference 是 Java 并发包(java.util.concurrent.atomic)中用于实现对象引用**无锁、线程安全更新**的核心类。它通过底层的 CAS(Compare-And-Swap)指令保证对引用变量的读-改-写操作原子性,避免使用 synchronized 或显式锁带来的开销和阻塞。
核心原理:CAS 保障引用更新的原子性
AtomicReference 内部持有一个 volatile 引用,并借助 CPU 提供的 CAS 指令完成“检查当前值是否等于预期值,是则更新为新值,否则失败”的原子操作。整个过程不加锁、不阻塞线程,适合高并发、低竞争场景。
- CAS 成功返回
true,表示更新完成;失败返回false,需由调用方决定重试或放弃 - volatile 语义确保引用的可见性:一个线程修改后,其他线程能立即看到最新值
- 不支持复合逻辑(如“先取值再计算再更新”),必须由用户自己循环重试(即自旋)
基本用法:set、get、compareAndSet
最常用的操作是初始化、读取、条件更新:
-
new AtomicReference<t>(initialValue)</t>:构造时可传入初始对象引用 -
get():获取当前引用值(等价于 volatile 读) -
set(newValue):无条件设置新引用(等价于 volatile 写) -
compareAndSet(expected, updated):仅当当前值 == expected 时,才设为 updated,返回是否成功
示例:实现一个线程安全的单例 Holder(非双重检查,仅演示 CAS):
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
MyService getService() {
MyService instance = holder.get();
if (instance == null) {
instance = new MyService();
if (!holder.compareAndSet(null, instance)) {
instance = holder.get(); // 竞争失败,取已设置的实例
}
}
return instance;
}
进阶技巧:updateAndGet 与 lazySet
Java 8+ 提供了更简洁的原子更新方法,减少手动循环代码:
-
updateAndGet(UnaryOperator<t> updateFunction)</t>:以当前值为输入,返回新值,自动重试直到成功(内部自旋) -
getAndUpdate(UnaryOperator<t> updateFunction)</t>:返回旧值,更新为新值 -
lazySet(newValue):延迟写入,不强制刷新缓存,适用于“只写不立即读”的场景(如链表尾指针更新),性能略优
例如:用 updateAndGet 实现计数器式对象切换(如切换配置对象):
// 原子地把当前配置升级为新版(假设 Config 支持 copyWithVersion)
Config newConfig = configRef.updateAndGet(old -> old.copyWithVersion(old.version + 1));
注意事项:ABA 问题与引用相等性
AtomicReference 默认使用 == 判断引用是否相等,不是 equals()。这意味着:
- 两个内容相同但不同地址的对象,会被视为不同值,CAS 可能意外失败
- 存在 ABA 问题:某引用从 A → B → A,CAS 会误认为未被修改(虽然罕见,但涉及链表、栈等结构时需警惕)
- 若需按内容比较,应封装对象并重写
equals/hashCode,或改用AtomicStampedReference(带版本戳)或AtomicMarkableReference(带标记位)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










