当我阅读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;
}
}
}
上面的类是如何使用最终字段的示例。线程执行读取器保证看到f.x的值3,因为它是最终的。不能保证看到y的值为4,因为它不是最终的。
这让我很困惑,因为编写器中的代码不是安全的发布,线程执行读者可能会看到f不是null,但是引用的对象的构造函数还没有完成,所以即使x是final,线程执行读取器无法保证看到fx
的值3这是我困惑的地方,如果我错了请纠正我,非常感谢你。
答案 0 :(得分:2)
这就是重点,这就是JMM中最终字段的优点。是的,编译器通常可以在对象完全构造之前分配对象的引用,这是 unsafe 发布,因为可以在部分构造的状态下访问对象。但是,对于 final 字段,JMM(和编译器)保证所有最终字段都将首先,之前分配对宾语。该发布可能仍然是不安全的,并且该对象在新线程访问时仍然只是部分构造,但至少最终字段将处于其预期状态。从Java Concurrency in Practice中的第16.3章开始:
初始化安全性使得可见性仅保证值 可以通过构造函数的最终字段到达 饰面。对于可通过非最终字段或值获得的值 施工后可能会发生变化,必须使用同步来确保 可视性。
我还建议阅读第16.3章以获取更多细节。