













深入理解 CAS 的核心原理,以及它在多线程场景下的工作机制、优缺点和实际应用,我会从基础概念到底层实现,用通俗易懂的方式帮你讲清楚。
CAS 是 Compare-And-Swap(比较并交换) 的缩写,是一种无锁的原子操作机制,也是实现并发编程的核心思想之一。它的核心目标是:在不使用锁的情况下,保证多线程对共享变量操作的原子性。
CAS 操作涉及三个核心参数:
V:要修改的共享变量(内存地址)A:预期值(线程读取到的变量当前值)B:新值(线程想要把变量改成的值)CAS 的执行流程可以概括为:
线程在更新变量
V时,先对比V的当前值是否等于自己之前读取的预期值A:
- 如果相等,说明没有其他线程修改过这个变量,就把
V的值更新为新值B,返回操作成功;- 如果不相等,说明其他线程已经修改过这个变量,当前线程不做更新,返回操作失败(线程可选择重试、放弃或执行其他逻辑)。
这个对比 + 交换的过程是CPU 级别的原子指令(如 x86 架构的 cmpxchg 指令),由硬件保证原子性,无需加锁。
假设两个线程(线程 1、线程 2)要对共享变量 j=0 执行加 1 操作,用 CAS 实现的过程:
j 的值为 0(预期值 A=0),准备更新为 1(新值 B=1);j 的值是否等于 0 → 是,将 j 改为 1,操作成功;j 的值为 0(预期值 A=0),准备更新为 1(新值 B=1);j 的值(此时已被线程 1 改为 1)≠ 预期值 0 → 操作失败;j 的值(现在是 1),再执行 CAS 把 j 改为 2。Java 中 java.util.concurrent.atomic 包下的原子类(如 AtomicInteger)就是基于 CAS 实现的,核心依赖 Unsafe 类(提供底层内存操作)。
核心代码示例(简化版):
public class AtomicInteger extends Number implements java.io.Serializable {
// 共享变量(volatile 保证可见性)
private volatile int value;
// Unsafe 类(JDK 内部类,提供底层 CAS 操作)
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset; // value 变量的内存地址偏移量
static {
try {
// 获取 value 变量在内存中的偏移量
valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
// 原子加1操作(核心 CAS 逻辑)
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
// Unsafe 的 getAndAddInt 方法底层逻辑(简化)
// var1:当前对象(AtomicInteger 实例)
// var2:value 变量的内存偏移量
// var4:要增加的值(如1)
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
// 1. 读取当前内存中的值(预期值 A)
var5 = this.getIntVolatile(var1, var2);
// 2. 执行 CAS:对比内存值是否等于 var5,是则更新为 var5+var4
// 循环直到 CAS 成功(自旋)
} while (!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
}
关键说明:
value 用 volatile 修饰,保证多线程间的可见性(一个线程修改后,其他线程能立即看到最新值);compareAndSwapInt 是 native 方法,底层调用 CPU 原子指令,保证对比 + 交换的原子性;do-while 循环自旋重试,直到 CAS 成功。AtomicStampedReference),把 “值 + 版本号” 作为对比依据。j = a + b),无法保证原子性,仍需用锁。| 特性 | CAS(无锁) | synchronized/ReentrantLock(有锁) |
|---|---|---|
| 核心机制 | 硬件原子指令 + 自旋 | 操作系统内核态锁(阻塞 / 唤醒线程) |
| 性能 | 低冲突时极高,高冲突时下降 | 低冲突时略差,高冲突时更稳定 |
| 适用场景 | 单一变量原子操作 | 复合操作、多变量操作 |
| 问题 | ABA、自旋开销 | 死锁、上下文切换开销 |
AtomicInteger 等原子类基于 CAS 实现,结合 volatile 保证可见性;此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。