CAS通过硬件原子指令实现无锁并发,核心是“读—比—写”三步不可分割,依赖乐观假设与调用方自旋重试,支持高效轻量同步但存在ABA、单变量限制及CPU空转问题。

CAS(Compare-And-Swap)不是靠锁实现线程安全,而是靠硬件原子指令直接保障“读—比—写”三步不可分割。它不阻塞线程,也不让出CPU,是无锁并发(lock-free)最核心的基石。
CAS的三个关键操作数
CAS必须同时指定三个值:
- 内存地址V:要修改的变量在内存中的位置(比如一个int型字段的地址)
- 预期值A:你“认为此刻它应该是多少”——通常是你上一次读到的值
- 新值B:你想把它改成的值
整个操作只有一条指令完成:若V处当前值等于A,则把B写入V;否则不做任何修改,返回失败。
底层靠CPU原子指令硬保证
现代处理器(如x86)提供CMPXCHG这类指令,它在电路层面锁定缓存行或总线,确保从读取、比较到写入全程不被中断。这不是JVM或Java库“模拟”的原子性,而是硬件原语级别的支持。
JDK中Unsafe.compareAndSwapInt()等方法,本质就是调用这类汇编指令。JVM会将它编译为一条CPU指令,而不是多条普通指令的组合。
为什么能实现无锁?关键在“乐观+自旋”
CAS默认假设冲突很少发生——你读完值,准备更新时,别人大概率没动过它。这种策略叫“乐观并发控制”。
- 成功:值未被改,直接更新,一气呵成
- 失败:值已被其他线程改过,CAS返回false,调用方自行决定是否重试(常见做法是循环重读+重试,即“自旋”)
没有synchronized那样的monitor enter/exit开销,也没有线程挂起/唤醒成本,适合高竞争但每次操作极轻量的场景(如计数器、状态标志位)。
注意它的典型局限
CAS强大但不是万能的:
- ABA问题:值从A→B→A,CAS误判为“没变”,其实中间已被改过。可用带版本号的AtomicStampedReference解决
- 只能单变量:一次CAS只能保护一个内存地址。多个字段需同步更新时,得靠AtomicReference包装对象或使用更高级结构(如LongAdder)
- 自旋可能空耗CPU:高竞争下反复失败、重试,会持续占用CPU周期,需结合退避策略或降级为锁
理解CAS,关键是抓住“硬件原子指令 + 乐观假设 + 调用方负责重试”这三点闭环。它把同步责任从内核/虚拟机下放到应用逻辑层,也因此更灵活、更轻量。










