【发布时间】:2018-04-24 16:33:38
【问题描述】:
当我读到jsr-133-faq 时,有疑问“最终字段在新 JMM 下如何工作?”,它说:
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;
int j = f.y;
}
}
}
上面的类是如何使用 final 字段的示例。保证执行 reader 的线程看到 f.x 的值 3,因为它是最终的。不能保证看到 y 的值 4,因为它不是最终值。
这让我很困惑,因为 writer 中的代码不是安全发布的,线程执行 reader 可能会看到 f 不是 null,但是 f 引用的对象的构造函数还没有完成,所以即使 x 是 final,无法保证执行 reader 的线程看到 f.x 的值 3。
这就是我困惑的地方,如果我错了,请纠正我,非常感谢。
【问题讨论】:
-
thread executing reader may see f is not null, but the constructor of the object witch f referenced is not finished yet这不可能发生,赋值发生在构造函数运行完成并且没有抛出异常之后。 -
哪种机制保证赋值的发生发生在构造函数运行完成之后?In Jeremy Manson's blog,他说编译器转换可以改变代码周围,使Helper构造函数中的代码在写入之后发生到辅助变量。我认为jsr-133-faq中的代码和Jeremy Manson博客中的代码是同一场景。
标签: java final safe-publication