cas原子性靠cpu的cmpxchg指令硬件保障,unsafe仅作java层调用桥梁;它通过缓存锁实现高效原子操作,但仅支持单变量、存在aba问题及自旋开销。

CAS 能保证原子性,靠的不是 Java 代码或 JVM 虚拟机逻辑,而是 CPU 硬件指令本身不可分割的执行能力。Unsafe 类只是把这条硬件能力“翻译”给 Java 程序用的桥梁。
CAS 的原子性来自 CPU 指令级保障
在 x86 架构上,CAS 对应的是 cmpxchg(Compare and Exchange)指令。这条指令由 CPU 直接执行,从取值、比较、写入全程在一个不可中断的周期内完成:
- 它被设计为“系统原语”,操作系统和硬件层面确保其执行期间不会被线程调度、中断或其它 CPU 核心干扰;
- 现代 CPU 多采用缓存锁(Cache Lock)而非总线锁来实现 cmpxchg——只要目标内存地址落在某个 CPU 核心的独占缓存行(MESI 协议中的 M 状态)中,就无需锁总线,大幅降低开销;
- 即使多个线程同时对同一变量调用 CAS,最终也只有一个线程能成功,其余全部失败返回 false,不存在中间态或部分更新。
Unsafe 是 Java 访问底层硬件的“合法后门”
sun.misc.Unsafe 不是普通工具类,它是 JVM 提供的、绕过 Java 安全模型的底层操作接口。它的作用不是实现 CAS,而是把 Java 方法映射到 native 层的 cmpxchg 调用:
- Unsafe 中的
compareAndSwapInt、compareAndSwapObject等方法都是 native 实现,内部直接调用 C++ 编写的 JVM 底层代码; - 这些 native 方法最终触发 CPU 的 cmpxchg 指令,并处理好内存屏障(Memory Barrier),保证可见性和有序性;
- Java 并发包(如 AtomicInteger、ConcurrentHashMap)全部基于 Unsafe 的 CAS 方法构建,而不是自己拼汇编或调系统调用。
为什么不能直接 new Unsafe?
Unsafe 被刻意限制使用,原因很明确:
- 它的方法可直接读写任意内存地址,等同于 C 语言指针操作,一旦出错会导致 JVM 崩溃或数据错乱;
- JVM 通过
getUnsafe()的类加载器校验机制,只允许 Bootstrap ClassLoader 加载的类(如 rt.jar 中的类)调用,防止应用层滥用; - 开发者需通过反射获取实例,这本身就是一种“你清楚风险才继续”的隐式提示。
CAS 不是万能的,得知道它不做什么
原子性只针对单个变量的一次 compare-and-swap 操作。它不解决:
- ABA 问题:值从 A→B→A,CAS 看不出中间变化,需配合版本号(如 AtomicStampedReference);
- 多变量原子更新:一次 CAS 只能操作一个字段,多个字段要打包成对象再用 AtomicReference;
- 自旋开销:失败后通常靠循环重试,高竞争下会空耗 CPU,需结合退避策略或降级为锁。











