CAS的原子性由CPU指令(如x86的cmpxchg)硬件保障,Unsafe仅作为Java调用该能力的桥梁;AtomicInteger等原子类通过Unsafe的compareAndSwapInt等native方法触发CPU指令,并配合volatile和自旋重试实现线程安全。

CAS 的原子性不是 Java 代码写的,而是 CPU 指令(比如 x86 上的 cmpxchg)硬件级保障的;Unsafe 类只是把这条能力“翻译”给 Java 用的桥梁。
Unsafe 是 CAS 在 Java 中的调用入口
Java 并发包里所有原子类(AtomicInteger、AtomicReference 等)都不自己拼汇编或调系统调用,而是统一依赖 sun.misc.Unsafe 提供的 native 方法:
- compareAndSwapInt(Object o, long offset, int expected, int update)
- compareAndSwapObject(Object o, long offset, Object expected, Object update)
- compareAndSwapLong(Object o, long offset, long expected, long update)
这些方法在 HotSpot JVM 中是 C++ 实现的,最终触发 CPU 的 cmpxchg 指令,并自动插入内存屏障,确保可见性和有序性。
原子类如何组合 Unsafe 实现线程安全操作
以 AtomicInteger 的 getAndIncrement() 为例,它内部调用的是 Unsafe 的 getAndAddInt() 方法:
立即学习“Java免费学习笔记(深入)”;
- 先用 getIntVolatile() 读取当前值(带 volatile 语义,保证可见)
- 再用 compareAndSwapInt() 尝试更新:仅当内存值仍等于刚读到的值时才成功
- 失败就重试,直到 CAS 成功为止——这就是典型的“乐观锁 + 自旋”模式
整个过程没有锁,不阻塞线程,但依赖 volatile 修饰的字段(如 AtomicInteger 中的 value)来配合可见性。
为什么必须用 Unsafe 而不是普通 Java 代码
因为普通 Java 字节码无法直接发出 cmpxchg 这类特权指令:
- Unsafe 是 JVM 提供的“合法后门”,绕过 Java 安全模型,允许直接操作内存地址和偏移量
- 它的方法都声明为 native,由 JVM 底层绑定到硬件能力
- 应用层不能直接 new Unsafe,必须通过反射获取实例——这是 JVM 对高危能力的显式约束
CAS 和 Unsafe 的配合有明确边界
它们高效但不万能:
- 只支持单变量一次原子更新,多字段需打包成对象再用 AtomicReference
- 存在 ABA 问题,需 AtomicStampedReference 等增强类型解决
- 高竞争下自旋会空耗 CPU,实际类库中常结合退避策略或降级为锁


















