Java中Unsafe类不直接实现CAS,而是通过调用JVM底层原子指令(如x86的cmpxchg)暴露CAS能力,供java.util.concurrent等上层构建无锁结构;其提供compareAndSwapInt/Long/Object三类基于字段偏移量的CAS方法,返回是否成功;因高危且受限,业务代码严禁直接使用,应优先选用AtomicInteger等封装好的原子类或JDK9+推荐的VarHandle。

Java 中 Unsafe 类本身不直接“实现”CAS,而是通过调用 JVM 底层的原子指令(如 x86 的 cmpxchg)暴露 CAS 能力,供上层(如 java.util.concurrent 包)构建无锁数据结构。你不能也不应直接在业务代码中使用 Unsafe 做 CAS——它被限制访问,且极易出错。
Unsafe 的 CAS 方法有哪些
Unsafe 提供了三类 CAS 相关方法,核心是基于字段偏移量(long offset)进行原子比较并交换:
compareAndSwapInt(Object obj, long offset, int expected, int x)compareAndSwapLong(Object obj, long offset, long expected, long x)compareAndSwapObject(Object obj, long offset, Object expected, Object x)
这些方法返回 boolean,表示是否成功(即当前值等于 expected 且已更新为 x)。注意:它们操作的是对象内存中指定偏移位置的字段,不是字段名——所以必须先用 objectFieldOffset 获取该字段在内存中的地址偏移。
如何获取 Unsafe 实例(仅作技术理解)
自 JDK 9 起,Unsafe.getUnsafe() 会检查调用类的 ClassLoader:只有 Bootstrap ClassLoader 加载的类才能获取实例。普通应用需通过反射绕过(仅用于学习或框架内部,生产环境禁用):
立即学习“Java免费学习笔记(深入)”;
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
Unsafe unsafe = (Unsafe) f.get(null);
但 JDK 17+ 进一步收紧反射权限,默认拒绝访问;若强行启用(如加 --add-opens=java.base/jdk.internal.misc=ALL-UNNAMED),仍属高危行为。
CAS 的实际落地靠的是 java.util.concurrent 工具类
真正安全、可维护的 CAS 使用方式是封装好的原子类,它们内部用 Unsafe,但对外屏蔽细节:
-
AtomicInteger:用unsafe.compareAndSwapInt实现incrementAndGet() -
AtomicReference:支持任意对象的 CAS 更新 -
AtomicStampedReference:解决 ABA 问题,带版本戳 -
VarHandle(JDK 9+ 推荐替代方案):标准化、更安全的底层变量访问机制,也基于Unsafe,但有更好封装和权限控制
例如:AtomicInteger casCount = new AtomicInteger(0); casCount.compareAndSet(0, 1); —— 这行代码背后就是 Unsafe 的 compareAndSwapInt,但你无需关心偏移量、内存布局或异常处理。
为什么不该在业务逻辑里手写 Unsafe CAS
直接使用 Unsafe 会带来严重风险:
- 内存偏移计算错误导致 JVM 崩溃(segmentation fault)
- 字段被 JIT 优化、重排序,破坏原子语义
- 不同 CPU 架构(ARM vs x86)对内存屏障要求不同,
Unsafe不自动适配 - 无法被 Java 内存模型(JMM)保证,线程可见性难控
- 违反模块化限制(JDK 9+ 模块系统默认封锁
jdk.internal.*)
如果你的目标是实现高性能并发结构(比如自定义队列),优先考虑 VarHandle 或复用 java.util.concurrent 已验证的组件;只有极少数基础库(如 Netty、Disruptor)会在严格受控下使用 Unsafe。


















