多线程请解释Java内存模型中规定的初始化安全 2 周,6 日 Questions & Answers 2369 有人能按照Java内存模型的要求解释初始化安全性吗李> final字段如何帮助实现初始化安全李> 构造函数在确保初始化安全方面扮演什么角色李>
# 1 楼答案 初始化安全性使外部线程可以看到处于完全构造(初始化)状态的对象。先决条件是对象不应过早发布,即在其构造函数中发布。一旦确保了这一点,JMM就需要对声明为final的字段执行某些行为。首先,所有final对象字段都保证被处于完全初始化状态的外部线程看到。这并不像听起来那么琐碎 考虑一个类: class A { List list; A() { list = Arrays.asList(some init expressions that adds 10 elements to list); } } 默认情况下,访问A's实例的list的线程不能保证在该列表中看到10个元素。事实上,这个线程甚至可以将list视为null。但是,如果list被声明为final,那么,按照JMM的要求,list必须始终用其中的10个元素初始化 其次,这个初始化保证不限于final字段本身,而是递归地扩展到它所引用的所有对象。例如,如果上面示例中的list是列表本身的列表,那么外部线程将确保看到内部列表已完全初始化 请注意,我们没有使用synchronized来实现内存可见性中的这种安全性(发生在关系之前)
# 1 楼答案
初始化安全性使外部线程可以看到处于完全构造(初始化)状态的对象。先决条件是对象不应过早发布,即在其构造函数中发布。一旦确保了这一点,JMM就需要对声明为
final
的字段执行某些行为。首先,所有final
对象字段都保证被处于完全初始化状态的外部线程看到。这并不像听起来那么琐碎考虑一个类:
默认情况下,访问
A's
实例的list
的线程不能保证在该列表中看到10个元素。事实上,这个线程甚至可以将list
视为null
。但是,如果list
被声明为final
,那么,按照JMM的要求,list
必须始终用其中的10个元素初始化其次,这个初始化保证不限于
final
字段本身,而是递归地扩展到它所引用的所有对象。例如,如果上面示例中的list
是列表本身的列表,那么外部线程将确保看到内部列表已完全初始化请注意,我们没有使用
synchronized
来实现内存可见性中的这种安全性(发生在关系之前)