From the book Java concurrency in practice :
To publish an object safely, both the
reference to the object and the
object’s state must be made visible to
other threads at the same time. A
properly constructed object can be
safely published by:
Initializing an object reference from a static initializer
Storing a reference to it into a volatile field or AtomicReference
Storing a reference to it into a final field of a properly constructed
objectStoring a reference to it into a field that is properly guarded by a
lock.
My questions are :
- What are the the differences between bullet points 2 and 3 ? I am interested in the difference between
volatileapproach andfinalapproach in terms of safe publication of the object . - What does he mean by final field of a properly constructed object in point 3 ? Before starting the bulleted points authors already mentioned that they are talking about a properly constructed object (which I assume is not letting the
thisreference to escape ). But once again why did they mention about properly constructed objects ?
volatilebasically means that any writes to that field will be visible from other threads. So when you declare a field as volatile:private volatile SomeType field;, you are guaranteed that if the constructor writes to that field:field = new SomeType();, this assignment will be visible by other threads that subsequently try to readfield.finalhas quite similar semantics: you have the guarantee that if you have a final field:private final SomeType field;the write to that field (either in the declaration or in the constructor):field = new SomeType();won’t be reodered and will be visible by other threads if the object is properly published (i.e. no escape ofthisfor example).Obviously, the main different is that if the field is final, you can only assign it once.
If, for example, you let
thisescape from the constructor, the guarantee provided by the final semantics is gone: an observing thread might see the field with its default value (null for an Object). If the object is properly constructed this can’t happen.Contrived example: