JDK 9中新增的库,是java.util.concurrent.atomic
和sun.misc.Unsafe
操作的等价替代。VarHandle是通用的对象的域的引用句柄,提供原子的操作方法。
直接看用法即可。
// 对象域
private volatile int state;
private volatile Thread runner;
private volatile WaitNode waiters;
// 通用句柄
private static final VarHandle STATE;
private static final VarHandle RUNNER;
private static final VarHandle WAITERS;
// 在类中查找域的位置,并初始化
static {
try {
MethodHandles.Lookup l = MethodHandles.lookup();
STATE = l.findVarHandle(FutureTask.class, "state", int.class);
RUNNER = l.findVarHandle(FutureTask.class, "runner", Thread.class);
WAITERS = l.findVarHandle(FutureTask.class, "waiters", WaitNode.class);
} catch (ReflectiveOperationException e) {
throw new ExceptionInInitializerError(e);
}
}
它提供get, set, compareAndSet
之类的原子操作。典型的用法如下,它首先传入实例引用(this),取得this对象中的state字段,对比是否等于NEW,如果是则赋值为COMPLETING,并且返回true,否则返回false。
if (STATE.compareAndSet(this, NEW, COMPLETING)) {
}
它的原理,我猜测和UNSAFE的版本非常像。
// 句柄,其实也是相对于类的偏移量
private static final long stateOffset;
private static final long runnerOffset;
private static final long waitersOffset;
static {
try {
UNSAFE = sun.misc.Unsafe.getUnsafe();
Class<?> k = FutureTask.class;
stateOffset = UNSAFE.objectFieldOffset
(k.getDeclaredField("state"));
runnerOffset = UNSAFE.objectFieldOffset
(k.getDeclaredField("runner"));
waitersOffset = UNSAFE.objectFieldOffset
(k.getDeclaredField("waiters"));
} catch (Exception e) {
throw new Error(e);
}
}
来看UNSAFE版本如何完成compaeAndSet。它同样传入对象实例,字段偏移量,从而对某个字段进行原子的对比更新。
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING))
参考
https://www.baeldung.com/java-variable-handles
https://segmentfault.com/a/1190000013544841
https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/VarHandle.html#compareAndSet-java.lang.Object…-