CAS本质是CPU提供的cmpxchg等原子指令,通过“读-比-写”三步不可分割保证线程安全;Java通过Unsafe类调用该指令,AtomicInteger等原子类基于此实现乐观锁自旋更新。

CAS 指令的本质是 CPU 级原子操作
CAS 不是 Java 语言层面的语法,而是由底层 CPU 提供的一条原子汇编指令(如 x86 上的 cmpxchg)。它在硬件层面保证“读-比-写”三步不可分割:从内存地址读出当前值,与预期值比较,若相等则写入新值,否则不修改。整个过程不会被线程调度中断,因此天然线程安全。
Unsafe 类是 Java 访问 CAS 的唯一桥梁
sun.misc.Unsafe 是 JVM 内部核心类,所有 public 的原子类(如 AtomicInteger、AtomicReference)都依赖它实现无锁操作。它的关键能力包括:
- 通过 objectFieldOffset() 获取对象字段在内存中的偏移量(相当于 C 中的指针地址)
- 提供 compareAndSwapInt/Long/Object 等 native 方法,把字段偏移量 + 预期值 + 新值传给 JVM,最终触发 CPU 的 cmpxchg 指令
- 绕过 Java 的类型检查和 GC 管理,直接读写堆内存——这也是它被标记为 “Unsafe” 的原因
一个典型调用链:AtomicInteger.incrementAndGet()
以 new AtomicInteger(0).incrementAndGet() 为例,其底层执行逻辑是:
- 先用 unsafe.getObjectVolatile() 读取当前 value 值(配合 volatile 保证可见性)
- 调用 unsafe.compareAndSwapInt(this, valueOffset, current, current + 1)
- 若返回 false(说明期间被其他线程改过),就循环重试(自旋),直到成功
这个“读-判-写-失败重试”的模式,就是乐观锁的典型实现,不需要阻塞或挂起线程。
为什么不能直接 new Unsafe()?
Unsafe 构造器是 private 的,且 getUnsafe() 方法做了严格校验:只允许由 Bootstrap ClassLoader(即 JDK 自身类)加载的代码调用。普通应用代码直接调用会抛出 SecurityException。实践中如需使用,只能通过反射绕过限制,但不推荐生产环境这么做——JUC 提供的原子类已封装好全部安全边界。

















