CAS(Compare-And-Swap)详解
CAS 是计算机科学中一种重要的原子操作,全称为 Compare-And-Swap(比较并交换)。它是现代并发编程的基石之一,广泛应用于 Java 并发包(JUC)、操作系统内核和数据库系统等领域。
1. 基本概念
CAS 操作包含三个参数:
- 内存位置(V)
- 预期原值(A)
- 新值(B)
操作逻辑伪代码:
if (V == A) {
V = B;
return true;
} else {
return false;
}
所有步骤作为一个原子操作执行
2. 底层实现原理
2.1 硬件支持
- 通过 CPU 的原子指令实现(如 x86 的
CMPXCHG指令) - 现代处理器普遍支持的多核原子操作
2.2 Java 中的实现
通过 sun.misc.Unsafe 类提供 native 方法:
public final native boolean compareAndSwapObject(
Object o, long offset,
Object expected, Object x);
public final native boolean compareAndSwapInt(
Object o, long offset,
int expected, int x);
3. 工作流程
以 AtomicInteger 的 incrementAndGet() 为例:
- 读取当前值(假设为 5)
- 计算新值(5 + 1 = 6)
- 执行 CAS(比较当前值是否仍为 5)
- 如果是,更新为 6
- 如果被其他线程修改(比如变为 7),则重试
4. 在 Java 中的典型应用
4.1 原子类
AtomicInteger count = new AtomicInteger(0);
count.incrementAndGet(); // 内部使用CAS
4.2 ConcurrentHashMap
// Java 8 putVal 中的CAS用法
if (casTabAt(tab, i, null, new Node<K,V>(hash, key, value, null)))
break;
4.3 AQS(AbstractQueuedSynchronizer)
// 尝试获取锁的CAS操作
compareAndSetState(0, 1)
5. 优缺点分析
优点:
- 无锁并发:避免线程阻塞/唤醒的开销
- 高性能:用户态操作,无需内核介入
- 无死锁:不存在传统锁的相互等待问题
缺点:
- ABA问题:值从A→B→A的变化无法感知
- 解决方案:添加版本号(AtomicStampedReference)
- 循环开销:高竞争时可能大量重试
- 单一变量:只能保证一个变量的原子性
6. ABA问题示例
AtomicReference<Integer> ref = new AtomicReference<>(100);
// 线程1准备将100→200
ref.compareAndSet(100, 200);
// 线程2先执行了:
ref.compareAndSet(100, 50);
ref.compareAndSet(50, 100); // 又改回100
此时线程1的CAS仍会成功,但中间状态已变化
解决方案:
AtomicStampedReference<Integer> ref =
new AtomicStampedReference<>(100, 0);
// 比较时同时检查值和版本戳
ref.compareAndSet(100, 200, stamp, stamp+1);
7. 与其他同步机制对比
| 机制 | 阻塞性 | 实现复杂度 | 适用场景 |
|---|---|---|---|
| synchronized | 阻塞 | 简单 | 通用场景 |
| CAS | 非阻塞 | 复杂 | 低竞争、原子操作 |
| Lock | 阻塞 | 中等 | 需要高级功能时 |
CAS 是现代并发库的基础,理解它对掌握 Java 并发编程至关重要。
7835

被折叠的 条评论
为什么被折叠?



