Bog*_* T. 6 java thread-safety
我在"Java Concurrency In Practice"中读到"在完全构造之前发布对象会损害线程安全性".有人可以解释一下吗?
new 运算符可以在类的构造函数完成之前返回一个值。因此,变量可能不会读取 null,但包含未初始化的类实例。这是由于字节重新排序而发生的。
一些澄清:从单线程的角度来看,JVM 允许对某些指令重新排序。传统上创建实例时,您可能会认为它是这样的:
事实上,JVM 可能会执行以下操作:
这具有性能优势,因为不需要再次查找地址。从单线程的角度来看,这不会改变逻辑的顺序。你的程序运行得很好。但这在多线程代码中带来了问题。这意味着可以在构造函数运行之前发布引用。因此,您需要一个“happens-before”规则来确保实例已完全初始化。将变量声明为 volatile dos 会强制执行此类发生在规则之前的规则。
有关重新排序的更多信息: http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#reordering