According to JCP (16.2.2. Safe Publication):
This happens-before guarantee is actually a stronger promise of visibility and ordering than made by safe publication. When X is safely published from A to B, the safe publication guarantees visibility of the state of X, but not of the state of other variables A may have touched. But if A putting X on a queue happens-before B fetches X from that queue, not only does B see X in the state that A left it (assuming that X has not been subsequently modified by A or anyone else), but B sees everything A did before the handoff (again, subject to the same caveat)
I'm wondering when safe publication can be without happens-before, i.e. w/o using volatile/atomics or synchronization (or via frameworks such as AQS which use any of listed inside)?
One case is final fields in immutable object, where you can publish it as is w/o any additional steps.
Are there any other cases?
UPD: re-read 3.5.3. Safe Publication Idioms, another case - "Initializing an object reference from a static initializer". Seems now these are all options.
I'm not aware of anything besides final
, and a glance at http://java.sun.com/docs/books/jls/third_edition/html/memory.html seems to confirm this. Chapter 17.4 deals with everything except final
, which is explained separately in 17.5.
It should be noted, though, that anything internal to the JVM must always be made visible before it can possibly contribute to a data race in the Java code. This affects mostly array lengths, virtual table pointers and String contents. These can never be seen as uninitialized or otherwise inconsistent.
All list of cases you may find in Java In Concurrency:
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
object; or
Storing a reference to it into a field
that is properly guarded by a lock.
static initialization is done inside synchronized(class)
, so it's very strong.
while final
semantics is weaker, I doubt the implementation is really that weak.
Doug Lea's had a proposal for more primitive fences, http://cs.oswego.edu/pipermail/concurrency-interest/2009-January/005743.html