最近,当我向 JMM 寻求与“最终”相关的保证时,我感到很困惑。这是 JMM 的摘录和示例
图 4 给出了一个示例,展示了最终字段与正常字段的比较。FinalFieldExample 类有一个最终的 int 字段 x 和一个非最终的 int 字段 y。一个线程可能执行方法 writer(),而另一个线程可能执行方法 reader()。因为 writer() 在对象的构造函数完成后写入 f,所以 reader() 将保证看到正确初始化的 fx 值:它将读取值 3。因此,reader() 方法不能保证看到它的值 4
class FinalFieldExample {
final int x;
int y;
static FinalFieldExample f;
public FinalFieldExample() {
x = 3;
y = 4;
}
static void writer() {
f = new FinalFieldExample();
}
static void reader() {
if (f != null) {
int i = f.x; // guaranteed to see 3
int j = f.y; // could see 0
}
}
}
我的困惑是对象'Obj'具有最终和非最终字段已完全初始化并被线程'T'引用,T只会看到最终字段的正确值?构造后未发生突变的非最终字段呢?我知道如果它们在构造线程'T'之后发生突变,可能看不到新值(除非该字段是 volatile )。但是,如果该字段是非最终的和非易失的并且在构造后没有发生突变,我该怎么办?
JVM 如何实现与 'final' 相关的保证?例如,对于 volatile 存在内存屏障。