Java CAS 与 Unsafe 深度解析
如果说 AQS 是并发框架的"内核设计",那么 CAS 和 Unsafe 就是"CPU 级指令暴露层"。
几乎所有 Java 并发能力,最终都会落到这两个关键词上。
一、为什么 Java 需要 CAS?
在并发世界里,我们要解决的核心问题只有一个:
多个线程同时修改同一份数据,如何保证正确性和性能?
传统方案:锁(Lock / synchronized)
-
优点:语义简单、安全
-
缺点:
- 线程阻塞 / 唤醒
- 上下文切换
- 可扩展性差
👉 在 高并发、短临界区 场景下,锁的代价非常高。
二、CAS 是什么?(Compare And Swap)
1️⃣ CAS 的定义
CAS 是一种乐观并发控制原语,由 CPU 原子指令支持。
它的语义是:
if (memory == expected)
memory = newValue
else
fail
2️⃣ CAS 的三个操作数
| 参数 | 含义 |
|---|---|
| V | 内存位置(地址) |
| A | 期望值(Expected) |
| B | 新值(Update) |
👉 这是一个不可分割的原子操作
三、CAS 在 Java 中的体现
AtomicInteger 示例
java
AtomicInteger i = new AtomicInteger(0);
i.incrementAndGet();
底层等价逻辑:
java
do {
int old = value;
} while (!CAS(value, old, old + 1));
👉 失败就重试,自旋直到成功
四、CAS 的三大问题(面试高频)
1️⃣ ABA 问题
A → B → A
CAS 只关心"当前值是否等于期望值",不关心"中间发生了什么"。
解决方案
AtomicStampedReferenceAtomicMarkableReference
2️⃣ 自旋开销
- 并发度高
- CAS 长时间失败
👉 会 白白消耗 CPU
解决思路:
- 限制自旋次数
- 结合 park/unpark
3️⃣ 只能保证单变量原子性
CAS 只能操作一个内存地址。
👉 多变量一致性仍然需要锁。
五、Unsafe 是什么?
1️⃣ Unsafe 的定位
java
sun.misc.Unsafe
Unsafe 是 JVM 提供的"后门 API",允许 Java 直接操作内存和线程。
⚠️ 名字就说明了一切:
用不好 = JVM 崩溃
2️⃣ 为什么 Unsafe 不对普通开发者开放?
- 绕过 Java 内存安全检查
- 绕过对象生命周期管理
- 绕过访问控制
👉 这是 JVM 实现者 / 并发框架作者的工具
六、Unsafe 提供了哪些核心能力?
1️⃣ CAS 原子操作(最重要)
java
compareAndSwapInt
compareAndSwapLong
compareAndSwapObject
AQS、AtomicXXX、FutureTask 全靠它。
2️⃣ 内存操作(堆外内存)
java
allocateMemory
freeMemory
getLong
putLong
👉 Netty / DirectBuffer 的基础。
3️⃣ 内存屏障(Memory Fence)
java
loadFence()
storeFence()
fullFence()
👉 用于实现 Java 内存模型(JMM)。
4️⃣ 线程控制
java
park()
unpark()
👉 AQS / FutureTask 阻塞机制的底层。
5️⃣ 对象实例化(绕过构造器)
java
allocateInstance(Class)
👉 反序列化框架的关键能力。
七、CAS + Unsafe 如何支撑整个 JUC?
AtomicXXX → Unsafe.CAS
AQS → Unsafe.CAS + park/unpark
ReentrantLock → AQS
FutureTask → Unsafe.CAS
ThreadPool → ctl CAS
👉 JUC ≈ Unsafe 的工程化封装
八、Unsafe 与 Java 内存模型(JMM)的关系
Unsafe 的 CAS 本身:
- 是原子操作
- 隐含内存屏障
保证:
- 写入对其他线程可见
- 禁止指令重排
👉 这是 volatile + CAS 能成立的根本原因
九、为什么 JDK 9 之后要"封禁" Unsafe?
问题:
- 滥用 Unsafe
- 不可维护
- 不可移植
解决方案:
| 能力 | 官方替代 |
|---|---|
| CAS | VarHandle |
| 堆外内存 | ByteBuffer / Panama |
| 原子类 | AtomicXXX |
👉 从"黑魔法"走向"标准能力"
十、Unsafe vs VarHandle(趋势)
| 对比点 | Unsafe | VarHandle |
|---|---|---|
| 安全性 | ❌ | ✅ |
| API 稳定性 | ❌ | ✅ |
| 可读性 | 差 | 好 |
| 推荐程度 | ❌ | ✅ |
十一、工程实践建议(专家经验)
✅ 你应该直接使用:
- AtomicXXX
- Lock / AQS
- ConcurrentXXX
❌ 不建议:
- 业务代码直接使用 Unsafe
- 手写 CAS 算法
👉 Unsafe 是"造轮子者"的工具,不是"用轮子者"的工具
CAS 是并发世界的最小原子操作,Unsafe 是 JVM 向上暴露这些原子能力的接口;整个 Java 并发体系,本质上都是对 CAS + Unsafe 的层层封装与约束。