【发布时间】:2015-10-22 08:13:12
【问题描述】:
我正在阅读Java® 语言规范 Java SE 8 版 和 17.5。 final 字段语义有一个示例 17.5-1。 Java 内存模型中的 final 字段(https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.5)。
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
}
}
}
描述状态:
一个线程可能执行方法编写器,另一个可能执行 方法阅读器。 因为 writer 方法在对象的构造函数之后写了 f 完成后,读者方法将保证正确看到 f.x 的初始化值:它将读取值 3。但是,f.y 是 不是最终的;因此,读者方法不能保证看到 值 4。
我用两个线程编写了一些代码来重现这种情况,但是当 reader 方法返回的不是 4 时,我无法获得案例?有构造函数总是将 f.y 设置为 4。
也许我无法理解某些事情。我会很感激澄清这一点。
编辑 谢谢大家,特别是 assylias。 Testing initialization safety of final fields 完全向我解释。对我来说,这些句子是最重要的:
从 Java 5.0 开始,保证所有线程都将看到 final 构造函数设置的状态。
实际上是确保构造函数在任何之前完成 随后的程序动作发生
【问题讨论】:
-
0 是有效结果这一事实并不意味着您的特定 JVM/OS/CPU 组合可以产生该结果。特别是我认为您无法在热点/x86 上创建这种情况。
-
这是 Jeremy Manson 的“官方”回答:stackoverflow.com/a/15517168/829571
标签: java