通过阅读Java 并发实践
我可以看到:
为了安全地发布对象,对象的引用和对象的状态必须同时对其他线程可见。正确构造的对象可以通过以下方式安全地发布:
- 从静态初始化器初始化对象引用
- 将对它的引用存储到易失性字段或 AtomicReference 中
- 将对它的引用存储到正确构造的对象的最终字段中
- 将对它的引用存储到由适当保护的字段中
锁。
然而,我对第二个习语感到困惑。自从volatile
只能保证引用对另一个线程可见 but 它没有同步它所引用的对象构造。那么如何保证可变对象被正确构造,什么情况下正在构造这个对象的线程被另一个线程中断了呢?
我们需要证明,构造一个对象并将其分配给一个易失性变量是在从该变量读取该对象之前发生的。
来自 JLS 第 17 章: https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html
If x and y是同一线程的操作,并且x出现在之前y按照程序顺序,那么hb(x,y)。
所以,构造一个对象发生在之前它被分配给一个易失性变量,从该线程的角度来看。
如果一个动作x 同步于以下动作y,那么我们还有hb(x,y)。
And:
If hb(x, y) and hb(y, z), then hb(x,z)。
如果我们可以证明写入 volatile 变量(动作y) 同步于读取变量(动作z),我们可以使用传递性发生在之前来表明构造对象(动作x) 发生在之前读取对象。幸运的是:
写入易失性变量v(§8.3.1.4)同步于所有后续读取v由任何线程(其中“后续”是根据同步顺序定义的)。
因此,我们可以看到,以这种方式发布时,正确构造的对象对任何线程都是可见的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)