Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
对此类的对象调用start()安全吗?Java并发实践中的一个例子_Java_Multithreading_Concurrency_Thread Safety_Safe Publication - Fatal编程技术网

对此类的对象调用start()安全吗?Java并发实践中的一个例子

对此类的对象调用start()安全吗?Java并发实践中的一个例子,java,multithreading,concurrency,thread-safety,safe-publication,Java,Multithreading,Concurrency,Thread Safety,Safe Publication,首先,我将给出我将要讨论的源代码的链接,因为复制/粘贴会使这个问题页面过长 在JCIP的清单5.15中,我设想在某些主要方法中,将创建CellularAutomata对象,然后对该对象调用start() 但是,这样做可以吗?调用对象的start方法时,它将使用Worker实例创建N个(处理器数)线程。似乎使用worker对象创建的N个线程可能看到该worker的不完整引用或对象 其背后的原因是,这个引用在调用CellularAutomata对象的构造过程中逃逸 新的Runnable()和新的Wo

首先,我将给出我将要讨论的源代码的链接,因为复制/粘贴会使这个问题页面过长

在JCIP的清单5.15中,我设想在某些主要方法中,将创建CellularAutomata对象,然后对该对象调用start()

但是,这样做可以吗?调用对象的start方法时,它将使用Worker实例创建N个(处理器数)线程。似乎使用worker对象创建的N个线程可能看到该worker的不完整引用或对象

其背后的原因是,这个引用在调用CellularAutomata对象的构造过程中逃逸 新的Runnable()和新的Worker(mainBoard.getSubBoard(count,i))

自【】名工人【】起;和循环载体屏障;如果是CellularAutomata对象的字段,则在该对象的start()方法中创建的线程可能无法看到处于正确状态的这些对象

我认为这与Holder的例子类似 其他线程可能看不到持有者字段。 我知道Holder示例有问题,因为字段不是最终字段,因此可能不可见,而在CellularAutomata中它们是最终字段。我读到只有最终字段的类在发布时保证其字段的可见性。然而,我也读到,虽然final字段可能是类的唯一字段,但是如果类没有正确构造,那么这种保证就没有了。在这个例子中,由于this引用转义,我假设它没有正确构造。下面是一个隐式让这个引用转义的例子,这与CellularAutomata中发生的事情类似

如果我的想法需要纠正,请告诉我,我将非常感激。这个并发过程让我充满了很多疑问和疑问,如果您有任何关于我可以在哪里学习并发以及Java中并发的基础的其他参考资料,请让我知道


谢谢

您可以阅读Java语言规范的相关章节:

第一个相关部分(我增加了重点):

当对象的 建造师完成只能看到对 对象在该对象完全初始化后将得到保证 查看该对象的最终值的正确初始化值 田地

在构造函数完成之前,
这个
引用不会被任何其他线程看到,所以这很好。
这个
引用从构造函数中“转义”并没有什么神奇之处;相关的事情是,其他线程不应该看到它(在构造函数完成之前)

JLS的下一段对此进行了扩展(我添加了强调和斜体):

final字段的使用模型很简单:设置final字段 对于该对象的构造函数中的对象;和不要写一个 指在另一个位置构造的对象 线程可以在对象的构造函数完成之前看到它。如果这 然后当另一个线程看到该对象时 线程将始终看到正确构造的版本 对象的最终字段


您可以阅读Java语言规范的相关章节:

第一个相关部分(我增加了重点):

当对象的 建造师完成只能看到对 对象在该对象完全初始化后将得到保证 查看该对象的最终值的正确初始化值 田地

在构造函数完成之前,
这个
引用不会被任何其他线程看到,所以这很好。
这个
引用从构造函数中“转义”并没有什么神奇之处;相关的事情是,其他线程不应该看到它(在构造函数完成之前)

JLS的下一段对此进行了扩展(我添加了强调和斜体):

final字段的使用模型很简单:设置final字段 对于该对象的构造函数中的对象;和不要写一个 指在另一个位置构造的对象 线程可以在对象的构造函数完成之前看到它。如果这 然后当另一个线程看到该对象时 线程将始终看到正确构造的版本 对象的最终字段


允许
这个
逃逸的危险在于它可能在完全构建之前就被看到了。在本例中,这不是问题,因为runnable在调用
start()
之前不会执行,这必须在构造函数完成之后执行

此外,除了
最终
字段保证之外,在
主板
的分配和runnable的执行之间至少还有两个额外的障碍。一个是通过what-will调用
Thread.start()
,然后是对
CylicBarrier.await()
的实际调用


所以我想说代码是非常安全的。

允许
这个
逃逸的危险在于它可能在完全构建之前就被看到了。在本例中,这不是问题,因为runnable在调用
start()
之前不会执行,这必须在构造函数完成之后执行

此外,除了
最终
字段保证之外,在
主板
的分配和