在此类的对象上调用start()安全吗?实践中来自Java并发的示例 [英] Is calling start() on a object of this class safe? An example from Java Concurrency in practice

查看:123
本文介绍了在此类的对象上调用start()安全吗?实践中来自Java并发的示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,我将提供指向我将要讨论的源代码的链接,因为复制/粘贴会使该问题页面过长.

First off, I will give links to the source code that I will be talking about since copy/paste would make this question page too long.

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

In Listing 5.15 http://jcip.net/listings/CellularAutomata.java of JCIP, I imagine that in some main method, one will create a CellularAutomata object and then call start() on that object.

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

However, is it okay to do so? When the object's start method is called, it will create N(number of processors) threads with instances of Worker. It seems though that the N threads that are created with the worker object might be seeing a incomplete reference or object of that Worker.

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

The reasoning behind it is that, the this reference escapes during the construction of the CellularAutomata object when calling new Runnable() and new Worker(mainBoard.getSubBoard(count, i))

并且由于Worker [] worker;和CyclicBarrier势垒;是CellularAutomata对象的字段,在该对象的start()方法中创建的线程可能无法看到处于适当状态的那些对象.

And since Worker[] workers; and CyclicBarrier barrier; are fields of the CellularAutomata object, the threads created in the start() method of that object might not be able to see those objects in a proper state.

我认为这类似于持有人的示例 http://jcip.net/listings/StuffIntoPublic .java http://jcip.net/listings/Holder.java 在其他线程可能看不到Holder字段的地方. 我知道Holder示例是有问题的,因为该字段不是最终的,因此可能不可见,并且在CellularAutomata中它们是最终的.我读过该类,只有最后的字段在发布时可以保证其字段的可见性.但是,我也读到,虽然final字段可能是类的唯一字段,但是如果没有正确构造该类,那么保证就不存在了.在本示例中,由于 this 引用已转义,因此我认为它的构造不正确.这是一个隐式让 this 引用转义的示例,类似于CellularAutomata中的操作. http://jcip.net/listings/ThisEscape.java

I am thinking this is similar to the Holder's example http://jcip.net/listings/StuffIntoPublic.java http://jcip.net/listings/Holder.java where the Holder's field might not be visible by other threads. I understand that the Holder example was problematic because the field was not final, and therefore might not be visible, and in the CellularAutomata they are final. I read that class with only final fields are guaranteed visibility for their fields when published. However, I also read that although final fields might be the only fields of a class, if the class is not properly constructed, then that guarantee is gone. And in this example, since the this reference escapes, I assume it is not properly constructed. Here is an example of implicitly letting the this reference escape which is similar to what's going on in CellularAutomata. http://jcip.net/listings/ThisEscape.java

请让我知道我的想法是否需要更正,我将不胜感激.这次并发之旅使我充满了很多疑问和问题,如果您还有其他参考资料可以学习并发性以及Java并发性的基础,请告诉我.

Please let me know if my thoughts need correction, I would really appreciate it. This concurrency journey has been filling me with so many doubts and questions and if you have any other references to where I can learn concurrency and the foundations for concurrency in Java, please let me know.

谢谢

推荐答案

您可以阅读Java语言规范的相关部分:

You can read the relevant section the Java Language Specification: 17.5. final Field Semantics

第一个相关部分(我加强调):

The first relevant section (emphasis added by me):

当一个对象被认为是完全初始化的 构造函数完成. 只能看到对 该对象已完全初始化之后的对象 查看该对象的final的正确初始化的值 字段.

An object is considered to be completely initialized when its constructor finishes. A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object's final fields.

在构造函数完成之前,其他任何线程都看不到this引用,所以很好. 构造函数中的this引用转义"没有什么神奇之处.相关的是没有其他线程可以看到(在构造函数完成之前).

The this references is not seen by any other thread before the constructor completes, so it's fine. There is nothing magic about the this reference "escaping" from the constructor; the relevant thing is that no other thread should see it (before the constructor completes).

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

The next paragraph in the JLS expands on this (emphasis and italics added by me):

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

The usage model for final fields is a simple one: Set the final fields for an object in that object's constructor; and do not write a reference to the object being constructed in a place where another thread can see it before the object's constructor is finished. If this is followed, then when the object is seen by another thread, that thread will always see the correctly constructed version of that object's final fields.

这篇关于在此类的对象上调用start()安全吗?实践中来自Java并发的示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆