1

我想知道 JAVA 中 synchronized 和 final 之间的关系。我已经阅读了几篇文章,每个人都提到应该使用 final 字段在构造函数中初始化一个对象,否则未初始化的对象可能会导致使用同一对象的多个线程之间出现同步问题。

为了。例如下面的代码:

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;
  }
 }  
}

读者可能会正确读取 x 的值,但可能会将 y 的值读取为 0,因为它没有被声明为 final。

为什么会这样?

4

2 回答 2

2

这与最终字段语义有关。JLS #17.5给出了一个很好的总结:

final 字段的使用模型很简单:在对象的构造函数中设置对象的 final 字段;并且不要在对象的构造函数完成之前在另一个线程可以看到它的地方写入对正在构造的对象的引用。如果遵循这一点,那么当另一个线程看到该对象时,该线程将始终看到该对象的最终字段的正确构造版本。

换句话说,只要this在构造过程中不让逃逸,就可以保证所有线程都会看到正确的 x 值(即 3)。

关于另一个字段 (y),在没有同步的情况下,不保证会看到哪个值(默认值或构造函数值)。

于 2013-02-24T00:20:37.327 回答
-1

final字段与线程无关。我怀疑你正在考虑的volatile领域确实有点像你描述的那样。

于 2013-02-24T00:28:56.840 回答