VarHandle 是 Java 9 引入的标准化原子操作工具,替代 Unsafe 和部分 AtomicXxx 类,基于 CAS 实现字段级无锁并发控制;它更灵活(支持任意字段、数组、堆外内存)、语义更明确(显式内存序)、性能更可控(直连 JVM 优化)。

VarHandle 是 Java 9 引入的底层原子操作工具,用于替代传统的 Unsafe 和部分 AtomicXxx 类,提供更安全、更通用、标准化的字段级无锁并发控制能力。它不依赖 synchronized,而是基于硬件支持的 CAS(Compare-and-Swap)指令实现原子读写与更新。
为什么用 VarHandle 而不是 AtomicXxx?
灵活性更高:AtomicInteger 等类只能操作固定类型和固定变量;VarHandle 可绑定任意对象的任意字段(包括非 public、数组元素、甚至堆外内存),支持泛型化操作。
语义更明确:通过 method handle 风格的 API(如 compareAndSet、getAcquire、setRelease)显式表达内存序(memory ordering),避免隐式语义歧义。
性能更可控:绕过 AtomicXxx 的封装开销,直接对接 JVM 内联优化,且可按需选择轻量级访问模式(如 plain vs. acquire/release)。
如何获取并使用 VarHandle?
通常通过 MethodHandles.privateLookupIn + VarHandle 查找机制获取字段句柄:
- 对 public 字段:用
MethodHandles.lookup().findVarHandle(Owner.class, "fieldName", FieldType.class) - 对 private 字段:需先用
privateLookupIn获取有权限的 lookup 实例(需模块开放或加--add-opens) - 对数组元素:用
MethodHandles.arrayElementVarHandle(int[].class)等工厂方法
拿到 VarHandle 后即可调用原子方法,例如:
boolean success = vh.compareAndSet(obj, expected, updated); // CAS int current = (int) vh.get(obj); // volatile 语义读 vh.set(obj, newValue); // volatile 语义写 vh.setOpaque(obj, newValue); // 不保证可见性顺序(仅当前线程)
关键内存序语义怎么选?
VarHandle 提供多组访问方法,对应不同 JMM 保证级别:
-
get()/set():等价于 volatile 读/写,具备 happens-before 关系 -
getAcquire()/setRelease():只保证单向同步(读后不重排、写前不重排),适合高性能场景(如自旋锁状态检查) -
getOpaque()/setOpaque():仅保证原子性,无内存序约束,类似普通字段但线程安全 -
compareAndSet()/weakCompareAndSetPlain():CAS 操作,后者可能失败重试但不保证强有序,适合无竞争路径
实际开发中,多数业务逻辑用 get/set 或 compareAndSet 即可;高并发基础设施(如队列、锁)才需精细控制 acquire/release。
典型应用场景示例
一个无锁计数器实现:
class LockFreeCounter {
private volatile long value = 0;
private static final VarHandle VH;
static {
try {
VH = MethodHandles.lookup()
.findVarHandle(LockFreeCounter.class, "value", long.class);
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
void increment() {
long current;
do {
current = (long) VH.get(this);
} while (!VH.compareAndSet(this, current, current + 1));
}
long get() { return (long) VH.get(this); }
}
注意:该实现未处理 ABA 问题,若需更强一致性,应结合版本号或使用 AtomicStampedReference 思路扩展。











