一、CAS核心概念
CAS(Compare-And-Swap)是一种原子操作,是现代CPU提供的硬件级指令,构成了无锁编程的基础。其操作逻辑可以用以下伪代码表示:
// 伪代码表示CAS操作
public boolean compareAndSwap(int expectedValue, int newValue) {
if (this.value == expectedValue) { // 比较当前值是否等于期望值
this.value = newValue; // 如果相等则更新为新值
return true;
}
return false;
}
二、CAS底层实现机制
1. 硬件支持
-
CPU指令:x86架构的
CMPXCHG指令,ARM的LDREX/STREX指令 -
原子性保证:CPU通过在总线加锁(LOCK前缀)或缓存锁定实现
2. Java中的实现
通过Unsafe类提供本地方法:
public final class Unsafe {
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);
public final native boolean compareAndSwapLong(Object o, long offset, long expected, long x);
}
三、CAS典型工作流程
-
读取内存值:获取当前共享变量的值V
-
计算新值:基于V计算出新值N
-
CAS尝试:执行CAS(V, N)
-
成功:更新完成
-
失败:回到步骤1(自旋)
// Java原子类中的典型实现 public class AtomicInteger { private volatile int value; public final int incrementAndGet() { for (;;) { int current = get(); int next = current + 1; if (compareAndSet(current, next)) return next; } } }
-
四、CAS三大关键问题
1. ABA问题
-
现象:值从A变为B又变回A,CAS会误认为没变化
-
解决方案:
-
添加版本号(AtomicStampedReference)
-
使用时间戳标记
// 带版本号的CAS AtomicStampedReference<Integer> ref = new AtomicStampedReference<>(100, 0); int stamp = ref.getStamp(); ref.compareAndSet(100, 101, stamp, stamp + 1);
-
2. 自旋开销
-
问题:长时间CAS失败会导致CPU空转
-
优化:
-
限制自旋次数(JVM自适应自旋)
-
退化为阻塞等待
-
3. 只能保证单个变量原子性
-
局限:无法保证多个变量的复合操作原子性
-
解决方案:
-
使用锁
-
合并变量到一个对象中
-
五、CAS在Java中的应用
1. 原子类(java.util.concurrent.atomic)
| 类名 | 用途 |
|---|---|
| AtomicInteger | 原子整型 |
| AtomicLong | 原子长整型 |
| AtomicReference | 原子引用 |
| LongAdder | 高并发计数优化 |
2. 并发容器实现
-
ConcurrentHashMap的节点插入
-
CopyOnWriteArrayList的写时复制
3. AQS(AbstractQueuedSynchronizer)
-
同步器状态变更
-
CLH队列中的节点状态管理
六、CAS性能特点
| 场景 | 性能表现 |
|---|---|
| 低竞争 | 极快(纳秒级) |
| 中等竞争 | 优于锁(避免上下文切换) |
| 高竞争 | 差于锁(CPU空转消耗) |
与锁的对比:
-
优点:无阻塞、无上下文切换、用户态完成
-
缺点:不适用于复杂操作、可能引起总线风暴
七、现代CPU对CAS的优化
-
缓存一致性协议(MESI):
-
减少总线锁定范围
-
只在缓存行无效化时加锁
-
-
LL/SC指令对(Load-Linked/Store-Conditional):
-
ARM/POWER架构的实现方式
-
比传统CAS更灵活
-
-
缓存行优化:
-
避免伪共享(@Contended注解)
-
提高CAS局部性
-
理解CAS原理对于编写高性能并发程序至关重要,它既是乐观锁的实现基础,也是现代并发容器的核心机制。在实际开发中,应:
-
优先使用JDK提供的原子类
-
高竞争场景考虑LongAdder等优化方案
-
复杂操作仍需配合锁使用
无锁编程原理深度解析&spm=1001.2101.3001.5002&articleId=147239016&d=1&t=3&u=d11b24993ac84119908650f868b2d03a)
2436

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



