java中unsafe.compareandswapint需先通过反射获取字段field,再调用objectfieldoffset得到偏移量offset,最后以obj、offset、期望值、新值为参数执行cas;失败返回false,需自旋重试,且字段须为volatile实例变量。

Java 中 Unsafe.compareAndSwapInt 并不直接暴露给普通开发者使用,它属于 JDK 内部的底层机制,被 java.util.concurrent.atomic 包(如 AtomicInteger)封装调用。要通过它操作对象字段的内存偏移量,核心在于:获取字段在对象中的偏移地址(long offset),再配合对象实例和期望值/新值进行 CAS 操作。
获取字段的内存偏移量(offset)
Unsafe 本身不提供“按字段名查 offset”的公开方法,但可通过 objectFieldOffset 获取指定 Field 对象对应的偏移量。这要求字段必须是 volatile 或至少是实例变量(静态字段需用 staticFieldOffset)。
- 先用反射拿到目标字段(如
private volatile int value) - 调用
Unsafe.objectFieldOffset(field)得到该字段相对于对象起始地址的字节偏移量 - 注意:该 offset 是 JVM 运行时计算的,不同 JVM 实现或版本可能不同,不可硬编码
调用 compareAndSwapInt 完成原子更新
拿到 offset 后,即可对具体对象实例执行 CAS:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
unsafe.compareAndSwapInt(obj, offset, expectedValue, newValue)-
obj是目标对象引用(不能为 null) -
offset是上一步获取的字段偏移量 - 该方法返回
boolean:true 表示 CAS 成功(当前值等于 expectedValue 并已更新为 newValue) - 失败时不抛异常,仅返回 false,需自行重试(如配合 while 循环实现自旋)
一个典型使用示例(模拟 AtomicInteger 的核心逻辑)
假设有一个简单计数器类:
<font size="2">class Counter {
private volatile int value = 0;
}</font>
使用 Unsafe 实现 increment:
<font size="2">Unsafe unsafe = getUnsafe(); // 需通过反射获取 Unsafe 实例
Field valueField = Counter.class.getDeclaredField("value");
long valueOffset = unsafe.objectFieldOffset(valueField);
Counter c = new Counter();
// 自旋写法
int current;
do {
current = unsafe.getIntVolatile(c, valueOffset); // 先读取当前值(volatile 语义)
} while (!unsafe.compareAndSwapInt(c, valueOffset, current, current + 1));</font>
注意:getIntVolatile 用于保证读取的可见性,避免因 CPU 缓存导致读到过期值;CAS 失败后必须重新读取最新值再尝试。
注意事项与限制
- Unsafe 是非标准 API,JDK 9+ 起默认禁止反射访问,需启动参数
--add-opens java.base/jdk.internal.misc=ALL-UNNAMED - 字段必须是非静态、可访问(private 字段需
setAccessible(true)) - offset 不跨 JVM 生效,不能序列化或持久化存储
- 不推荐在业务代码中直接使用;应优先使用
AtomicInteger、AtomicReference等封装好的类 - CAS 只保证单个字段的原子性,多字段协同更新需额外设计(如用 AtomicReference 包装整个对象)
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










