可变句柄、易失性和内存访问



我正在努力理解Varhandles,但有些示例包含了不同的变量可见性方法。

例如

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
class Point {
volatile int x;
private static final VarHandle X;
static {
try {
X = MethodHandles.lookup().
findVarHandle(Point.class, "x",
int.class);
} catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
// ...
}

示例显示了易失性的x字段。有必要吗?我的意思是,如果你有一个volatile字段,那么我们有一个内存屏障和其他与程序顺序相关的机制等。但从我的角度来看,在这个例子中,volatile是不必要的,否则它会对性能产生重大影响。从另一方面来说,Varhandle提供了所有必要的工具来安全地做到这一点。

什么是正确的解决方案?

这取决于情况。

VarhandlegetVolatile()/setVolatile()可以访问x,如果它被声明为volatile:

返回变量的值,具有读取的内存语义,就好像变量被声明为volatile一样。

但这只会在您通过VarHandle访问x时处理这种情况。

如果任何代码直接访问x,则仍然需要将其声明为易失性,因为否则JIT仍然可以将x缓存在内部寄存器中并只读取一次-例如,在以下代码中:

while (x < 10) {
// do something with x
}

从性能角度来看,这并不重要——通过VarHandle访问x不会比直接访问x快。(如果您将x声明为volatile,但通过不遵守volatile语义的VarHandleget()方法访问它,可能会出现异常,但随后会遇到并发问题。(

最新更新