阅读实践中的Java并发
我可以看到:
要安全地发布对象,必须同时使对象的引用和对象的状态对其他线程可见。正确构造的对象可以通过以下方式安全地发布:
然而,我对第二个成语感到困惑。由于volatile
只能保证引用对另一个线程可见,但它不会同步对象构造(它引用)。那么如何保证可变对象被正确构造,构造该对象的线程被另一个线程中断了?
答案 0 :(得分:6)
我们需要证明构造一个对象并将其分配给一个volatile变量是在从该变量中读取之前发生的。
如果 x 和 y 是同一个线程的操作, x 按照程序顺序出现在 y 之前,然后 hb(x,y)。
因此,对象的构造发生在之前,从该线程的角度将分配给易变量。
如果某个操作 x与同步 y,,那么我们还有 hb(x,y)。
和
如果 hb(x,y)和 hb(y,z),那么 hb(x,z)。
如果我们可以证明写入volatile变量(action y )同步 - 读取变量(action z ),我们可以使用发生在之前的传递性来表明构造对象(action x )在读取对象之前发生。幸运的是:
写入易失性变量 v (§8.3.1.4)与任何线程同步 v 的所有后续读取(其中) “后续”是根据同步顺序定义的。
因此,我们可以看到,当以这种方式发布时,任何线程都可以看到正确构造的对象。
答案 1 :(得分:1)
结果:volatile
保证变量总是从所有线程共享的内存中读取 - 如果值发布在volatile
变量中,则必须之前是完全构造的。
换句话说,如果没有公布volatile
值,那么没有其他线程会知道它 - 很可能是正在构建的结果&#39 ;可以驻留在CPU缓存中或JVM使用的内存中,作为我自己的目的使用的空间;你讨厌Java代码,不要问它里面有什么,它不是你的业务"。
答案 2 :(得分:1)
volatile只能保证引用对另一个线程是可见的,但它没有引用它所引用的对象构造的同步。
是。你是对的。您可以在下面的问题中找到有关volatile变量的内部细节的更多详细信息:
Difference between volatile and synchronized in Java
那么如何保证可变对象被正确构造,构造该对象的线程被另一个线程中断了什么呢?
您必须使用其他编程结构来实现线程安全:使用synchronized
构造或synchronized
构造的替代。
请参阅以下相关的SE问题: