可变对象安全发布,只有一个线程写

时间:2017-11-09 03:56:29

标签: java concurrency

让线程X中构造非线程安全的可变对象AA将构建后的X传递给线程BB变异XA永远不会再次访问X

X是否始终能够正确显示B的状态?

X是否有效地限制线程?

我对 Java Concurrency in Practice 的阅读似乎表明X未正确发布但我不能在运行数百万的测试装备中导致线程B出现任何问题重复。我怀疑这只是运气不好。

对于背景,X代表了许多复杂的类,我无法控制这些类是由仅具有Java基础知识的建模者创作的。强烈优选X没有同步块或其他并发机制或要求。

我目前正在通过让线程AX B调用X的线程安全工厂来解决此问题,从而使MATCH (:SomeLabel{someProperty:false})-[*..999999]->(x) WITH distinct x SET x.someProperty = false 线程受限制。

1 个答案:

答案 0 :(得分:0)

仅对最终字段安全发布

Java内存模型并不能保证对象X将完全发布(完全构造)到线程A

要确保这一点,您需要使其成为不可变的(所有成员字段为final)或同步。 引用JSR-133

  

最终字段的语义已得到加强,以实现线程安全的不可变性   没有明确的同步。这可能需要诸如商店门槛等步骤   设置最终字段的构造函数的结尾。

只有你需要避免的是在构造函数完成之前将字段泄漏出类。

<强>测试

jcstress实际上是一个展示出版期间赛车后果的示例项目:JMMSample_06_Finals.java

请注意,必须采取一些措施来复制问题,例如使用许多字段。 JMM的实现自然取决于您使用的特定JRE,并且使用的内存屏障的影响取决于所使用的硬件。

在使用Oracle JDK 8的硬件上,我无法使用带有jcstress的示例重现不安全的出版物。

<强>同步

有一个&#34;发生在之前&#34;所有同步动作之间的关系。这称为同步顺序。基本上,当您使用任何同步机制时,您可以保证之前的操作在其之后可见。

正如Java Language Specification中所述:

  

如果程序正确同步,则程序的所有执行都将显示为顺序一致

在实践中

在实践中,由于使用该对象的线程无法看到构造函数中的操作,因此很难遇到问题。 主要原因是使用同步机制。您可以检查一些确保javadoc中之前发生关系的操作:Memory Visibility

正如我在jcstress样本中提到的那样,JRE现在似乎非常善于确保一致的结果,即使它根据语言规范不需要。