Thanks for the response.
I was intentionally vague in my first post because I'm not interested in all the ways that an object reference can be made visible to different threads. When it does occur, and the reference in question refers to an immutable object, does that reference ever need synchronization? Why? This is what my first post is asking.
Before discussing it further I should clarify my vocabulary.
First of all, the term
synchronization includes the use of both volatile variables as
well as synchronized blocks. Therefore, if I need to make the reference a volatile one, "synchronization" was needed.
According to Brian Goetz book, "Java Concurrency In Practice":
An object instance is
immutable if it meets the following criteria:
- Its state cannot be modified after construction
- All its fields are final
- It is properly constructed (that the "this" reference does not escape during construction)
(See the following article to read more about letting "this" escape during construction: http://www.ibm.com/developerworks/java/library/j-jtp0618.html)
An object is
published when it is made available to code outside of its current scope - such as by storing an object reference where other code can find it (ie a public instance variable), returning the reference from a public method, or passing the reference to a method in another class.
<hr />
With that vocabulary in mind, we can talk about what kinds of safety guarantees are available for immutable objects and references to immutable objects.
Goetz talks about this when dealing with initialization safety:
- Immutable objects can be safely accessed even when synchronization is not used to publish the object reference.
- Initialization safety allows properly constructed immutable objects to be safely shared across threads without synchronization, regardless of how they are published - even if published using a data race.
- With the exception of immutable objects, it is not safe to use an object that has been initialized by another thread ...
Therefore, it appears that no synchronization is needed when
constructing an immutable object. No volatile reference is needed. No synchronized block around the reference is needed.
However, the reference may still need synchronization if it is modified after that. For instance:
Assume s is visible to different threads:
ImmutableObject x = new ImmutableObject();
.... later in the code
s = x;
The reference s is not involved in construction so its not guarded by the initialization safety guarantees. In this case, synchronization is needed.
Lastly, it's probably dangerous to rely on initialization safety at all in real code. If the criteria for immutable objects listed above are not met, it cannot be used. If the final fields change after construction (see http://stuffthathappens.com/blog/2007/10/13/you-can-change-final-fields/), then initialization safety cannot necessarily be relied upon either.
I think good programming etiquette requires the use of some kind of synchronization around the reference, although its nice to know initialization safety is there.
Any other questions or comments are greatly appreciated.
Thanks.