CAS是CPU提供的原子指令,JVM通过Unsafe封装为AtomicXXX类;它基于“预期值匹配才更新”实现乐观锁,失败需手动重试或降级;ABA问题在对象引用中需用AtomicStampedReference解决。

Java CAS 不是靠“教程”解的,而是靠理解它在并发场景中怎么用、为什么这么设计、哪里容易出错。所谓“百问百答”,本质是把核心概念拆透、把常见误区踩实、把典型用法练熟。
CAS 是什么:不是语法,是硬件能力的封装
CAS(Compare-And-Swap)不是 Java 关键字,也不是 JVM 特性,它是 CPU 提供的一条原子指令(如 x86 的 cmpxchg),JVM 通过 Unsafe 类把它暴露出来,再由 java.util.concurrent.atomic 包里的类(比如 AtomicInteger)封装成易用接口。
- 它需要三个参数:内存地址 V、预期值 A、新值 B
- 只做一件事:若 V 当前值等于 A,就把 V 改成 B;否则什么都不改,返回当前 V 值
- 整个过程不可中断——这是硬件保证的,不是 Java 代码“写得够快”就能实现的
CAS 怎么用:别直接碰 Unsafe,优先用 AtomicXXX
你几乎不需要手写 Unsafe.compareAndSwapInt。JDK 已经为你准备了开箱即用的工具:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- AtomicInteger:适合计数器、序列号、简单状态标记
- AtomicReference:适合更新对象引用,比如无锁链表节点
- AtomicStampedReference:专门用来防 ABA,给引用加版本戳
- LongAdder / DoubleAdder:高并发累加场景下比 AtomicInteger 更高效(分段累加 + 最终合并)
CAS 为什么失败:不是 bug,是设计逻辑的一部分
CAS 失败不等于出错,而是它“乐观”的体现:
立即学习“Java免费学习笔记(深入)”;
- 线程读到旧值 A,准备改成 B,结果另一线程抢先改成 C → 当前线程 CAS 失败,自旋重试
- 如果一直失败,可能说明竞争太激烈,要考虑是否该换同步方式(如 ReentrantLock)
- 失败本身不抛异常,返回 false 或原值,你要自己判断并决定下一步(重试?降级?记录?)
CAS 的坑怎么避:ABA 不是传说,但要分场景看
ABA 问题真实存在,但不是所有地方都会踩:
- 整型变量(如 AtomicInteger)极少出现语义级 ABA:100→50→100 和“没变过”对业务影响通常不大
- 对象引用才真正危险:比如无锁栈中,节点被弹出、回收、又复用为新节点,地址相同但内容已不同
- 解决它不用造轮子:AtomicStampedReference 把值和版本号打包操作,每次修改 stamp +1,A→B→A 就变成 (1,A)→(2,B)→(3,A),CAS 自然失败

















