During initialization of a shared object, the object must only be accessible to the thread constructing it. However, the object can be published safely (that is, made visible to other threads) once it is initialized. The Java Memory Model (JMM) allows multiple threads to observe the object after its initialization has begun, but before it has concluded. Consequently, it is important to ensure that a partially initialized object is not published.
This guideline rule prohibits publishing a reference to a partially initialized member object instance before initialization has concluded. Guideline Rule TSM01-J. Do not let the (this) reference escape during object construction prohibits the this
reference of the current object from escaping.
...
Consequently, the reference to the helper
instance should not be published before the Foo
class's constructor has finished its initialization. (See guideline rule TSM01-J. Do not let the (this) reference escape during object construction.)
...
Wiki Markup |
---|
The JMM guarantees that any final fields of an object are fully initialized before a published object becomes visible \[[Goetz 2006|AA. Bibliography#Goetz 06]\]. By declaring {{n}} final, the {{Helper}} class is made [immutable|BB. Definitions#immutable]. Furthermore, if the {{helper}} field is declared volatile in compliance with guidelinerule [VNA01-J. Ensure visibility of shared references to immutable objects], {{Helper}}'s reference is guaranteed to be made visible to any thread that calls {{getHelper()}} after {{Helper}} has been fully initialized. |
...
This compliant solution requires that helper
be declared volatile and class Helper
be immutable. If it were not immutable, the code would violate guideline rule VNA06-J. Do not assume that declaring a reference volatile guarantees visibility of the members of the referenced object, and additional synchronization would be necessary. (See the next compliant solution.) And, if the helper
field were non-volatile, it would violate guideline rule VNA01-J. Ensure visibility of shared references to immutable objects.
...
Because the Helper
object can change state after its construction, synchronization is necessary to ensure the visibility of mutable members after initial publication. Consequently, the setN()
method is synchronized to provide the visibility of the n
field in this compliant solution. (See guideline rule VNA06-J. Do not assume that declaring a reference volatile guarantees visibility of the members of the referenced object.)
...
If the helper
field in the Foo
class is not declared volatile, the n
field should be declared volatile so that a happens-before relationship is established between the initialization of n
and the write of Helper
to the helper
field. This is in compliance with guideline rule VNA06-J. Do not assume that declaring a reference volatile guarantees visibility of the members of the referenced object. This is required only when the caller (class Foo
) cannot be trusted to declare helper
volatile.
Because the Helper
class is declared public, it uses a private lock to handle synchronization in conformance with guideline rule LCK00-J. Use private final lock objects to synchronize classes that may interact with untrusted code.
...