20
  1. 有人可以按照 Java 内存模型的要求解释初始化安全吗?
  2. final字段如何帮助实现初始化安全
  3. 构造函数在确保初始化安全方面起什么作用?
4

2 回答 2

29

初始化安全性提供了外部线程在其完全构造(初始化)状态下看到的对象。前提是对象不应过早发布,即。在它的构造函数中。一旦确保了这一点,JMM 就要求声明为final. 首先,final保证所有对象字段都可以在完全初始化的状态下被外部线程看到。这并不像听起来那么简单。

考虑一个类:

class A {
   List list;
   A() {  
      list = Arrays.asList(some init expressions that adds 10 elements to list);
    }

}

list默认情况下,访问of实例的线程A's不能保证在该列表中看到 10 个元素。事实上,这个线程甚至可以list看作null. 但是,如果list声明为final,则根据 JMM 的要求,list必须始终显示为在其中使用 10 个元素进行初始化。

其次,这种初始化保证不限于final字段本身,而是递归地扩展到它所引用的所有对象。例如,如果list上面示例中的 是列表本身的列表,则外部线程保证将内部列表视为完全初始化。

请注意,我们没有使用任何地方synchronized来实现内存可见性(发生前关系)的这种安全性。

于 2012-07-03T08:46:34.530 回答
4

1. 初始化安全性允许在不使用同步的情况下跨线程安全地共享正确构造的不可变对象,无论它们是否使用数据竞争发布。

2. 具有最终字段的对象,初始化安全性防止使用对该对象的引用的初始加载对构造的任何部分进行重新排序。

于 2012-07-03T07:14:16.793 回答