请解释 Java 内存模型中阐述的初始化安全性

  1. 有人可以解释Java内存模型所要求的初始化安全性吗?
  2. 最终字段如何帮助实现初始化安全
  3. 构造函数在确保初始化安全方面扮演什么角色?

答案 1

初始化安全规定外部线程在其完全构造(初始化)状态下可以看到对象。先决条件是对象不应过早发布,即。在其构造函数中。确保这一点后,JMM 要求声明为 的字段具有某些行为。首先,保证外部线程在其完全初始化状态下能够看到所有对象字段。这并不像听起来那么微不足道。finalfinal

考虑一个类:

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

}

默认情况下,不保证访问实例的线程在该列表中看到 10 个元素。实际上,此线程甚至可以将 .但是,如果声明为 ,则根据 JMM 的要求,必须始终显示为使用 10 个元素进行初始化。listA'slistnulllistfinallist

其次,此初始化保证不限于字段本身,而是以递归方式扩展到它引用的所有对象。例如,如果上面的示例中是列表本身的列表,则外部线程可以保证看到内部列表已完全初始化。finallist

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


答案 2

1. 初始化安全允许在线程之间安全地共享正确构造的不可变对象,而无需使用同步,即使它们使用数据竞赛发布。

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