Java CAS 与 Unsafe 深度解析

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 只关心"当前值是否等于期望值",不关心"中间发生了什么"。

解决方案
  • AtomicStampedReference
  • AtomicMarkableReference

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 的层层封装与约束。


相关推荐
后端AI实验室4 小时前
用AI写代码,我差点把漏洞发上线:血泪总结的10个教训
java·ai
程序员清风6 小时前
小红书二面:Spring Boot的单例模式是如何实现的?
java·后端·面试
belhomme6 小时前
(面试题)Redis实现 IP 维度滑动窗口限流实践
java·面试
Be_Better6 小时前
学会与虚拟机对话---ASM
java
开源之眼8 小时前
《github star 加星 Taimili.com 艾米莉 》为什么Java里面,Service 层不直接返回 Result 对象?
java·后端·github
Maori3169 小时前
放弃 SDKMAN!在 Garuda Linux + Fish 环境下的优雅 Java 管理指南
java
用户9083246027310 小时前
Spring AI 1.1.2 + Neo4j:用知识图谱增强 RAG 检索(上篇:图谱构建)
java·spring boot
小王和八蛋10 小时前
DecimalFormat 与 BigDecimal
java·后端
beata10 小时前
Java基础-16:Java内置锁的四种状态及其转换机制详解-从无锁到重量级锁的进化与优化指南
java·后端
IT探险家10 小时前
你的第一个 Java 程序就翻车?HelloWorld 的 8 个隐藏陷阱
java