Skip to Content
面试题库Juc[面试题] CAS的执行原理是什么?它有什么问题?什么情况下适合使用?

[面试题] CAS的执行原理是什么?它有什么问题?什么情况下适合使用?

📖 版块 A:知识讲解版 (温故知新)

  • CAS (Compare And Swap) 定义:CAS 是乐观锁思想在计算机科学中的一种具体实现机制,全称是“比较并交换”。它包含三个核心操作数:内存地址 V、预期原值 E 和拟写入的新值 N。它的核心逻辑是:如果内存地址 V 当前的值等于预期原值 E,就将 V 的值更新为 N,否则什么都不做。

  • 执行原理(底层揭秘)

    1. 硬件级支持:CAS 操作之所以能够保证“比较和更新”这两个步骤不被其他线程打断,是因为它在底层是由 CPU 硬件直接提供的一条原子指令来保证的。比如在 x86 架构下,对应的是 lock cmpxchg 指令。
    2. Java 层的实现:Java 代码主要通过 sun.misc.Unsafe 类提供的 compareAndSwapInt 等 native 方法,向下调用 C++ 写的虚拟机底层代码,最终映射为 CPU 上的原子指令。
  • CAS 面临的三大问题

    1. ABA 问题:假如一个变量的值从 A 变成了 B,然后又变回了 A,此时另一个做 CAS 操作的线程去检查时会发现它的值还是 A,从而误以为它没有被修改过,CAS 操作就会成功执行。
    2. 循环时间长、CPU 开销大:CAS 一般配合死循环(自旋)来使用。如果并发竞争非常激烈,CAS 会频繁失败并不断重试,这会让 CPU 一直在空转,极大地拉高 CPU 的负载。
    3. 只能保证一个共享变量的原子操作:CAS 只能针对一个内存地址进行原子替换,无法直接保证跨多个变量(或多个步骤)的复合操作的原子性。
  • 适用场景

    1. 读多写少、写冲突较少:低竞争环境下,CAS 不需要将线程挂起和唤醒,避免了用户态与内核态的切换,性能远高于 synchronized
    2. 原子类操作与非阻塞数据结构:例如 AtomicInteger 进行计数,或者 ConcurrentLinkedQueue 进行无锁并发入队/出队。

🎤 版块 B:面试实战版 (高手逐字稿)

Q:CAS 的执行原理是什么?它有什么问题?什么情况下适合使用?

💬 高手逐字稿

CAS,也就是 Compare And Swap,它是 Java 无锁并发编程的核心,本质上是乐观锁思想的一种落地实现。

关于它的执行原理,可以从 Java 层和系统层两个维度来看。在 Java 层,我们是通过 Unsafe 类的 native 方法发起的调用;而到了最底层,其实是依赖了 CPU 硬件提供的一条原子指令,比如 x86 架构下的 cmpxchg 指令。在多核环境下,这条指令执行期间会锁住总线或者通过缓存一致性协议,来确保“比较并替换”这整个动作的绝对原子性,中间绝不会被其他线程的上下文切换给打断。

虽然 CAS 避免了传统重量级锁带来的线程挂起和内核态切换开销,但在实际应用中它也存在三个典型的痛点:

第一是著名的 ABA 问题。如果一个值从 A 改成了 B,紧接着又改回了 A,那么 CAS 在比对时就会误认为这个值从未被修改过。对于某些像栈弹出压入这种对修改过程敏感的业务,这会导致致命的逻辑错误。我们的解决思路也很成熟,就是引入一个递增的版本号或者时间戳,在 Java 里可以直接使用 AtomicStampedReference 来解决。

第二是自旋导致的 CPU 开销问题。我们用 CAS 通常会包裹在一个 while 死循环里。如果并发冲突非常严重,线程就会不断地自旋重试,这会极大地白白消耗 CPU 资源。针对这个瓶颈,我们在高并发计数场景下,会选择使用 JDK 8 引入的 LongAdder。它的思想是通过内部维护一个 Cell 数组进行分段累加,将单个热点变量的 CAS 竞争分散到多个变量上,典型的“空间换时间”的优化思路。

第三点是它只能保证单一变量的原子性。如果业务要求同时更新两个以上的变量,普通的 CAS 就无能为力了。这种时候,我们通常会把多个变量封装进一个实体对象中,然后利用 AtomicReference 对整个对象进行 CAS 替换。

最后,我认为在技术选型上,CAS 最适合用在竞争不算太激烈,并且业务逻辑极短、操作粒度极小的场景中(比如做个计数器,或者改变一个状态标志位)。在这种轻量级场景下,它的性能是吊打悲观锁的。但如果业务代码又长又复杂,或者并发写极其惨烈,强行用 CAS 反而会引发 CPU 飙升的灾难,老老实实加锁反而是更稳妥的选择。

最后更新于:
⏱️

登录后开始阅读

当前 MVP 版本只开放邮箱密码登录注册。完成登录后即可进入面试题内容。

还没有账号?先去注册