请解释Java内存模型中详述的初始化安全性
- 有人可以解释Java内存模型所要求的初始化安全性吗?
- 最终字段如何帮助实现初始化安全性 ?
- 构造函数在确保初始化安全性方面起什么作用?
初始化安全性允许外部线程在其完全构造(初始化)状态下看到对象。 前提条件是不应过早发布对象,即。 在它的构造函数中。 一旦确保这一点,JMM就要求声明为final
的字段具有某些行为。 首先,所有final
对象字段都被保证在外部线程处于完全初始化状态时被看到 – 这并不像听起来那么简单 –
考虑一堂课
class A{ List list ; A() { list = Arrays.asList(some init expressions that adds 10 elements to list); } }
默认情况下,访问A
实例list
的线程不会保证看到该列表中的10个元素。 实际上,这个线程甚至可以将list
视为null
。 但是,如果list
被声明为final
,那么,根据JMM的要求, list
必须始终显示为使用10个元素进行初始化。
其次,这种初始化保证不仅限于final
字段本身,而是递归地扩展到它引用的所有对象。 例如,如果上面示例中的列表是list
本身的list
,则外部线程保证将内部列表视为完全初始化。
请注意,我们没有使用synchronized
来实现内存可见性的这种安全性(在关系之前发生)。
1.初始化安全性允许在不使用同步的情况下跨线程安全地共享正确构造的不可变对象 ,而不管它们是否使用数据争用发布。
2.具有最终字段的对象,初始化安全性防止在初始加载对该对象的引用的情况下重新排序构造的任何部分 。