CAS 与原子类
CAS(Compare-And-Swap)是现代 CPU 提供的原子指令,是 Java 无锁编程的基础。java.util.concurrent.atomic 包中的原子类都基于 CAS 实现,提供了高性能的并发操作。
CAS 原理
概念
CAS 操作包含三个操作数:
- V:内存位置
- E:期望值
- U:新值
只有当 V 的当前值等于 E 时,才将 V 更新为 U。
伪代码
CAS 的硬件支持
x86 指令
x86 架构提供 lock cmpxchg 指令:
CAS 的 ABA 问题
ABA 问题是 CAS 的经典问题:值从 A 变成 B 再变回 A,对于 CAS 操作来说看起来「没变」,但实际上已经被人修改过。
ABA 问题的解决
原子类家族
基本类型
引用类型
数组类型
字段更新器
CAS vs 锁
对比
性能对比
CAS 的问题
自旋开销
线程饥饿
高竞争下,某些线程可能长时间无法成功。
只能保证单一变量
CAS 只能保证单个变量的原子性,多个变量的复合操作需要额外的同步。
LongAdder 详解
LongAdder 是解决高竞争下 CAS 性能问题的经典方案。
设计思想
核心思想
- 分段:将单个计数分散到多个 Cell
- 减少冲突:不同线程写入不同 Cell
- 求和:读取时将所有 Cell 的值求和
LongAdder vs AtomicLong
使用场景
实战应用
无锁计数器
单例模式
环形缓冲区
本章总结
核心要点:
- CAS 原理:比较当前值与期望值,相等才更新
- 硬件支持:x86 的
lock cmpxchg指令 - ABA 问题:使用版本号(AtomicStampedReference)解决
- 原子类:AtomicInteger/Long/Reference 等基于 CAS
- LongAdder:分段计数,解决高竞争下 CAS 性能问题
- CAS vs 锁:低竞争选 CAS,高竞争选锁
CAS 是无锁编程的基础。下一节我们将详细对比 LongAdder 与 AtomicLong。