javamultithreadingconcurrencythread-safetysafe-publication

Is calling start() on a object of this class safe? An example from Java Concurrency in practice


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.

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.

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.

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))

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.

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

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.

Thank you


Solution

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

    The first relevant section (emphasis added by me):

    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.

    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).

    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.