1

来自Java 理论与实践:修复 Java 内存模型,第 2 部分

The new JMM also seeks to provide a new guarantee of initialization safety -- that as long as an object is properly constructed (meaning that a reference to the object is not published before the constructor has completed), then all threads will see the values for its final fields that were set in its constructor, regardless of whether or not synchronization is used to pass the reference from one thread to another.

那么在构造函数中初始化的非最终字段是什么?从a reference to the object is not published before the constructor has completed我可以得出结论,行为与最终字段相同。这是对的吗?

4

2 回答 2

3

参加这个简单的课程:

class Example {
    final int i;
    int j;
    Example() { i = 5; j = 5; }
}

在构造过程中不会发布对对象的引用,因此 JMM 保证访问新创建的 Example 实例的所有读取线程都会看到i = 5. 无论实例是如何发布的,情况都是如此。

j = 0但是,如果实例未安全发布,这些相同的线程可能会看到(即默认值)。安全出版习语包括:

  • 从静态初始化器初始化实例
  • 将对实例的引用标记为 volatile
  • 将对实例的引用标记为最终的
  • 同步所有访问
于 2013-05-28T09:27:20.283 回答
1
  • 对于 volatile 变量,保证写入对所有线程立即可见。无论写入是否在构造函数中完成,情况都是如此。

  • 对于非易失性变量,写入可能不会立即对其他线程可见。无论写入是否在构造函数中完成,情况都是如此。

一个特例是 final 字段。一旦构造函数完成,对对象的最终字段的写入保证对所有线程都是可见的。

你可以在这里阅读更多。

于 2013-05-28T09:33:19.540 回答