Java CAS 原理深度解析
Java CAS(Compare-And-Swap)原理深度解析
CAS(Compare-And-Swap)是一种乐观锁机制,包含三个操作数:
- M(内存位置) – 需要更新的内存地址
- V(预期值) – 预期要读取的原始值
- 新值 – 要更新的新值
只有当 M 的值与 V 一致时,才会将 M 更新为新值,否则操作失败。
一、CAS 工作原理
CAS 操作在底层通过 CPU 指令实现,常见的有 x86 架构的 CMPXCHG 指令。
1. 原子性保证
public class CASDemo {
private int value;
// CAS 自增示例
public void increment() {
int oldValue;
do {
oldValue = value;
} while (!compareAndSwapInt(oldValue, oldValue + 1));
}
private native boolean compareAndSwapInt(int expected, int newValue);
}
2. 自旋机制
CAS 通过循环自旋实现重试,直到成功或满足终止条件。
二、ABA 问题
ABA 问题是 CAS 机制的经典隐患。
问题场景
- 线程 T1 读取值为 A
- 线程 T2 将值从 A 改为 B
- 线程 T2 又将值从 B 改回 A
- 线程 T1 执行 CAS,发现值仍是 A,操作成功
虽然值看起来没变,但中间状态已被修改过。
解决方案:版本号机制
// AtomicStampedReference 解决 ABA 问题
AtomicStampedReference<Integer> ref = new AtomicStampedReference<>(1, 0);
// 获取带版本的值
int[] stampHolder = new int[1];
Integer value = ref.get(stampHolder);
int stamp = stampHolder[0];
// 带版本的 CAS 操作
ref.compareAndSet(1, 2, stamp, stamp + 1);
三、AtomicInteger 实现
1. AtomicInteger
AtomicInteger atomicCount = new AtomicInteger(0);
// 原子自增
atomicCount.incrementAndGet(); // 返回自增后值
atomicCount.getAndIncrement(); // 返回自增前值
// 条件更新
atomicCount.compareAndSet(0, 1); // 仅当值为 0 时设置为 1
2. 其他原子类
// 长整型
AtomicLong atomicLong = new AtomicLong(0);
// 布尔值
AtomicBoolean flag = new AtomicBoolean(false);
// 数组
AtomicIntegerArray array = new AtomicIntegerArray(10);
// 引用
AtomicReference<String> ref = new AtomicReference<>("initial");
四、CAS vs synchronized
| 特性 | CAS | synchronized |
|---|---|---|
| 锁机制 | 乐观锁 | 悲观锁 |
| 阻塞情况 | 不阻塞,自旋重试 | 可能阻塞线程 |
| 适用场景 | 竞争不激烈 | 竞争激烈 |
五、应用场景
1. 计数器
AtomicInteger counter = new AtomicInteger(0);
// 并发安全地计数
for (int i = 0; i < 1000; i++) {
new Thread(() -> {
counter.incrementAndGet();
}).start();
}
2. 无锁数据结构
// 自定义无锁栈
public class LockFreeStack {
private AtomicReference<Node> head = new AtomicReference<>();
public void push(Node node) {
Node oldHead;
do {
oldHead = head.get();
node.next = oldHead;
} while (!head.compareAndSet(oldHead, node));
}
}
六、性能注意事项
- 自旋开销 – 高竞争时自旋会消耗 CPU 资源
- ABA 问题 – 必要时使用版本号机制
- 伪共享 – 使用 @Contended 注解避免
七、总结
CAS 是 Java 并发编程的核心技术之一。理解其原理、ABA 问题和应用场景,可以帮助开发者选择更合适的并发方案。在低竞争场景下,CAS 通常比 synchronized 性能更优;但在高竞争场景下,需要谨慎使用。



发表评论