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

2024-06-28

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

在清单 5.15 中http://jcip.net/listings/CellularAutomata.java http://jcip.net/listings/CellularAutomata.java在 JCIP 中,我想象在某些主要方法中,人们将创建一个 CellularAutomata 对象,然后对该对象调用 start() 。

然而,这样做可以吗?当调用该对象的 start 方法时,它将使用 Worker 实例创建 N(处理器数量)线程。似乎使用工作对象创建的 N 个线程可能会看到该工作人员的不完整引用或对象。

其背后的原因是,this在调用时构建 CellularAutomata 对象期间引用转义 new Runnable() 和 new Worker(mainBoard.getSubBoard(count, i))

由于 Worker[] 工人;和 CyclicBarrier 屏障;是 CellularAutomata 对象的字段,在该对象的 start() 方法中创建的线程可能无法看到处于正确状态的这些对象。

我认为这与持有人的例子类似http://jcip.net/listings/StuffIntoPublic.java http://jcip.net/listings/StuffIntoPublic.java http://jcip.net/listings/Holder.java http://jcip.net/listings/Holder.java其中 Holder 的字段可能对其他线程不可见。 我知道 Holder 示例是有问题的,因为该字段不是最终的,因此可能不可见,而在元胞自动机中它们是最终的。我读到只有最终字段的类在发布时保证其字段的可见性。然而,我还读到,虽然最终字段可能是类的唯一字段,但如果类没有正确构造,那么这种保证就消失了。在这个例子中,由于this引用转义,我认为它没有正确构造。这是隐式让this引用转义类似于元胞自动机中发生的情况。http://jcip.net/listings/ThisEscape.java http://jcip.net/listings/ThisEscape.java

如果我的想法需要纠正,请告诉我,我将非常感激。这段并发之旅让我充满了很多疑虑和问题,如果您对我可以在哪里学习并发以及 Java 并发基础有任何其他参考,请告诉我。

谢谢


允许的危险this逃避的是在它完全建成之前它可能会被看到。在这种情况下,这不是问题,因为可运行程序不会执行,直到start()被调用,必须在构造函数完成之后。

此外,除了final现场保证,至少有两个额外的发生在之前分配之间的障碍mainBoard以及可运行程序的执行。一是调用Thread.start()将会是什么最后进入屏障的线程 https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CyclicBarrier.html#CyclicBarrier-int-java.lang.Runnable-, which 发生在之前已启动线程中的任何操作。 https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility然后是实际的调用CylicBarrier.await(), which 发生-之前属于障碍行动一部分的行动 https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CyclicBarrier.html#CyclicBarrier-int-java.lang.Runnable-.

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐