Java final&安全发布

时间:2018-04-24 16:33:39

标签: java final safe-publication

当我阅读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

这是我困惑的地方,如果我错了请纠正我,非常感谢你。

1 个答案:

答案 0 :(得分:2)

这就是重点,这就是JMM中最终字段的优点。是的,编译器通常可以在对象完全构造之前分配对象的引用,这是 unsafe 发布,因为可以在部分构造的状态下访问对象。但是,对于 final 字段,JMM(和编译器)保证所有最终字段都将首先之前分配对宾语。该发布可能仍然是不安全的,并且该对象在新线程访问时仍然只是部分构造,但至少最终字段将处于其预期状态。从Java Concurrency in Practice中的第16.3章开始:

  

初始化安全性使得可见性仅保证值   可以通过构造函数的最终字段到达   饰面。对于可通过非最终字段或值获得的值   施工后可能会发生变化,必须使用同步来确保   可视性。

我还建议阅读第16.3章以获取更多细节。