Skip to content

CAS(Compare and Swap)


一、是什么?

CAS(Compare and Swap)是一种无锁并发原子操作,用于在多线程环境下保证共享变量的原子性更新。其核心逻辑是:

“如果内存位置V的值等于预期值A,则将该位置更新为新值B;否则不更新并返回当前值。”

在Java中,CAS通过sun.misc.Unsafe类的本地方法实现(如compareAndSwapInt),但开发者通常使用java.util.concurrent.atomic包下的工具类(如AtomicInteger)间接操作。


二、解决什么问题

  1. 锁竞争开销:传统锁(如synchronized)在高并发时线程切换开销大,CAS通过硬件级原子指令避免锁竞争。
  2. 原子操作需求:解决多线程下i++等非原子操作的安全问题,无需加锁。
  3. 死锁风险:无锁机制规避了死锁可能性。

三、核心方法

AtomicInteger中的典型方法:

java
public final boolean compareAndSet(int expect, int update) // JDK标准API
public final int getAndIncrement() // 内部基于CAS实现自增

四、应用场景

  1. 计数器:如网站访问量统计(AtomicLong)。
  2. 状态标志:轻量级状态切换(如线程池状态)。
  3. 无锁数据结构ConcurrentHashMap的桶节点更新、LinkedBlockingQueue
  4. 乐观锁:数据库版本号更新、分布式锁(如Redis的Lua脚本)。

五、Java示例

java
import java.util.concurrent.atomic.AtomicInteger;

public class CASDemo {
    public static void main(String[] args) {
        AtomicInteger count = new AtomicInteger(0); // 初始值为0
        
        // 模拟10个线程并发自增
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    count.getAndIncrement(); // 内部使用CAS自增
                }
            }).start();
        }
        
        // 等待所有线程结束
        try { Thread.sleep(1000); } 
        catch (InterruptedException e) { e.printStackTrace(); }
        
        System.out.println("最终结果: " + count.get()); // 正确输出10000
    }
}

六、与锁的区别

特性CAS锁(如synchronized)
机制无锁(硬件级原子指令)阻塞式锁
线程阻塞无阻塞(自旋重试)可能阻塞线程
适用场景低竞争、简单操作高竞争、复杂临界区
性能高并发下吞吐量更高竞争激烈时性能下降明显
死锁风险可能发生死锁

七、重要注意事项

  1. ABA问题
    • 问题:值从A→B→A,CAS误认为未被修改。
    • 解决:JDK 8+ 使用AtomicStampedReference添加版本号。
    java
    AtomicStampedReference<Integer> ref = new AtomicStampedReference<>(100, 0);
    ref.compareAndSet(100, 101, stamp, stamp + 1); // 检查值+版本号
  2. 自旋开销:高竞争时频繁重试消耗CPU资源。
  3. 单一变量限制:只能保证单个变量的原子性,复合操作需结合其他机制。
  4. JDK 8+增强
    • LongAdder替代AtomicLong应对高竞争计数器场景(分段CAS)。
    • CompletableFuture内部使用CAS优化异步任务状态更新。

八、总结

CAS是Java无锁并发的基石,通过硬件指令实现高效原子操作,适用于计数器、状态标志等场景。其优势是高性能、无死锁,但需警惕ABA问题及自旋开销。JDK 8+提供了LongAdderStampedReference等优化工具,开发者应结合场景选择CAS或锁机制。