CAS在Java中通过Atomic类间接使用,底层调用Unsafe的native方法和CPU原子指令;需配合volatile保证可见性,注意ABA问题、单变量限制及高竞争性能下降。

CAS(Compare and Swap)在 Java 中不是直接调用的底层指令,而是通过 java.util.concurrent.atomic 包中的一系列原子类间接使用——这些类内部封装了 Unsafe.compareAndSwap* 等 native 方法,由 JVM 调用 CPU 的原子指令(如 x86 的 cmpxchg)来保证操作不可中断。
核心用法:用 Atomic* 类替代普通变量
不用自己写 CAS 循环,Java 已为你封装好常用模式。例如:
-
计数场景:用
AtomicInteger替代int count,调用incrementAndGet()或addAndGet(1),内部自动完成“读取→计算→CAS 写回”三步,失败则重试,对用户完全透明。 -
状态标记:用
AtomicBoolean管理开关,compareAndSet(false, true)成功才执行后续逻辑,避免重复初始化或双重检查失效。 -
引用更新:用
AtomicReference<T>安全替换对象引用,比如无锁栈的push操作中更新头节点。
手动控制 CAS 流程:compareAndSet() 方法
当需要自定义重试逻辑或条件更新时,可显式调用 compareAndSet(expected, newvalue):
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 它返回
boolean,true表示更新成功,false表示当前值已变,需重新获取最新值再试。 - 典型写法是 while 循环 + CAS,即“自旋重试”:
int current;
do {
current = atomicInt.get();
} while (!atomicInt.compareAndSet(current, current + 1)); - 注意避免无限自旋:若竞争激烈,应考虑退化为锁或加 yield/sleep,防止 CPU 空转。
配合 volatile 保证可见性
CAS 本身不解决内存可见性问题。所以原子类的底层字段都用 volatile 修饰:
立即学习“Java免费学习笔记(深入)”;
-
volatile确保每次读取都是主内存最新值,避免线程从本地缓存读到过期值导致 CAS 失败。 - 它还禁止指令重排序,使 CAS 前后的读写操作顺序符合预期。
- 也就是说,CAS + volatile 共同构成“读取最新值 → 比较 → 原子写入”的完整安全链。
避开常见陷阱
CAS 不是万能解药,使用时需留意:
-
ABA 问题:值从 A→B→A,CAS 误判为未变。可用
AtomicStampedReference加版本戳解决。 - 只能更新单个变量:无法原子更新多个字段。涉及多字段一致性时,仍需锁或事务机制。
- 高竞争下性能下降:大量线程反复自旋重试,浪费 CPU。适合低到中等竞争场景。

















