CAS是Java无锁原子操作的核心机制,AtomicReference基于CPU硬件指令实现“读-比-写”原子性,依赖volatile保证可见性、Unsafe调用底层CAS、配合自旋重试实现线程安全更新,并需注意ABA问题。

CAS(Compare-And-Swap)是 Java 并发包中实现无锁原子操作的核心机制,AtomicReference 正是基于它来保证对象引用更新的线程安全性——不是靠锁,而是靠硬件级的原子指令反复比对并更新。
底层依赖 CPU 的 CAS 指令
AtomicReference 内部持有一个 volatile 引用字段(如 value),并通过 Unsafe 类调用 JVM 底层的 CAS 操作(如 compareAndSet)。这个操作由 CPU 直接支持,能在一个不可中断的步骤里完成“读取当前值 → 比较是否等于预期值 → 若是则写入新值”三步,整个过程原子执行。
例如:
- 线程 A 读到当前引用是
obj1,想把它换成obj2; - 同时线程 B 把它改成了
obj3; - A 执行 CAS 时发现当前值已不是
obj1,操作失败,可选择重试或放弃。
compareAndSet 是核心入口方法
AtomicReference.compareAndSet(expectedValue, newValue) 是最常用的方法,返回 boolean 表示是否成功。它内部调用 Unsafe 的 compareAndSwapObject,传入对象地址、字段偏移量、旧值和新值。
立即学习“Java免费学习笔记(深入)”;
关键点:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 必须用
==判断引用相等(不是equals),因为 CAS 比的是内存地址; - volatile 保证每次读都从主存加载,避免线程本地缓存导致的脏读;
- 失败不阻塞,适合高竞争下配合自旋逻辑使用。
配合自旋实现无锁更新逻辑
单纯一次 compareAndSet 可能失败,常见做法是用循环重试,直到成功为止:
AtomicReference<Counter> ref = new AtomicReference<>(new Counter(0));
Counter current, next;
do {
current = ref.get();
next = new Counter(current.value + 1); // 不可变对象更安全
} while (!ref.compareAndSet(current, next));
这段代码实现了线程安全的计数器更新。注意:如果 Counter 是可变对象,需确保更新不破坏原子性(比如用 new 创建新实例,而非修改原对象字段)。
ABA 问题与 AtomicStampedReference
CAS 只关心“值是否变化”,不关心“怎么变的”。若引用从 A → B → A,CAS 会误认为没变而更新成功,可能引发逻辑错误(如链表操作中的节点复用)。
解决办法:
- 用
AtomicStampedReference,给引用带上版本戳(int stamp),每次更新 stamp 加 1; - 或用
AtomicMarkableReference标记位区分状态; - 多数业务场景(如状态机切换、配置更新)中 ABA 不影响正确性,无需过度处理。
不复杂但容易忽略:volatile 语义 + 硬件 CAS + 用户态自旋,三者缺一不可。AtomicReference 不是魔法,而是把并发控制权交还给开发者,让设计更贴近数据本身的变化逻辑。

















