Java多线程如何理解CAS:Compare and Set 准则,一文详解!

compareAndSet 的作用是什么?

compareAndSet(expect, update):

如果当前值等于 expect,就把它改成 update,返回 true

否则不改,返回 false

这是 CAS(Compare and Swap)思想的核心。

总结

AtomicInteger 用 CAS 代替锁实现线程安全。

CAS = 比较 + 交换:如果没被别人改过就更新,否则重试。

优点:无锁,性能高(适合高并发)。

缺点:可能自旋多次,导致 CPU 占用高。

疑惑的源代码如下

public int incrementAndGet(AtomicInteger var) {
    int prev, next;
    do {
        prev = var.get();
        next = prev + 1;
    } while ( ! var.compareAndSet(prev, next));
    return next;
}

incrementAndGet() 与 CAS 执行过程详解

我们可以用一个具体的场景,带有多线程干扰的过程,一步一步演示 incrementAndGet() 是如何通过 CAS(Compare-And-Set) 确保线程安全的。


✅ 前提

AtomicInteger var = new AtomicInteger(5);
  • 初始值 = 5

  • 当前线程执行 incrementAndGet(var),同时假设 可能有其他线程修改这个值


✅ 逐步执行过程

Step 1:第一次尝试

prev = var.get();    // prev = 5
next = prev + 1;     // next = 6

此时 prev = 5next = 6
线程尝试更新:

var.compareAndSet(5, 6)
  • 如果成功 → 说明值还没被改过,更新为 6。
  • 如果失败 → 说明值被其他线程改了,需要重试。

假设此时另一个线程修改了值

  • 其他线程把 var 改成 10

Step 2:compareAndSet 失败

  • compareAndSet(5, 6) 比较当前值和 prev
    • 当前值 = 10,prev = 5 → 不相等 → CAS 失败
  • 进入 while 重新循环。

Step 3:第二次尝试

prev = var.get();    // prev = 10(重新读取当前值)
next = prev + 1;     // next = 11

尝试更新:

var.compareAndSet(10, 11)
  • 当前值 = 10,prev = 10 → 相等 → 更新成功

Step 4:返回结果

  • 更新完成,next = 11,返回 11

✅ 为什么这样做?

  • 即使中间有并发修改,这个循环会一直重试,直到 compareAndSet 成功。
  • 保证线程安全而且无锁(lock-free)

✅ 完整执行示例

假设:

  • 初始值:5
  • 线程 A 调用 incrementAndGet()
  • 线程 B 把值改成 10

执行顺序:

A: prev=5, next=6
B: var=10
A: CAS(5,6) 失败
A: prev=10, next=11
A: CAS(10,11) 成功 → 返回11
posted @ 2025-08-31 10:25  AlphaGeek  阅读(8)  评论(0)    收藏  举报