Java Reference
In-Depth Information
variable—the reference to the new object. If you do not ensure that publishing the shared
reference
happens-before
another thread loads that shared reference, then the write of the ref-
erence to the new object can be reordered (from the perspective of the thread consuming the
object) with the writes to its fields. In that case, another thread could see an up-to-date value
for the object reference but
out-of-date values for some or all of that object's state
—a par-
tially constructed object.
Unsafe publication can happen as a result of an incorrect lazy initialization, as shown in Fig-
ure 16.3. At first glance, the only problem here seems to be the race condition described in
identical, you might be willing to overlook these (along with the inefficiency of possibly cre-
ating the
Resource
more than once). Unfortunately, even if these defects are overlooked,
UnsafeLazyInitialization
is still not safe, because another thread could observe a
reference to a partially constructed
Resource
.
Listing 16.3. Unsafe Lazy Initialization.
Don't do this.
Suppose thread
A
is the first to invoke
getInstance
. It sees that
resource
is
null
, in-
stantiates a new
Resource
, and sets
resource
to reference it. When thread
B
later calls
getInstance
, it might see that
resource
already has a non-null value and just use the
already constructed
Resource
. This might look harmless at first, but
there is no happens-
beforeorderingbetweenthewritingofresourceinAandthereadingofresourceinB
. A data
race has been used to publish the object, and therefore
B
is not guaranteed to see the correct
state of the
Resource
.
The
Resource
constructor changes the fields of the freshly allocated
Resource
from
their default values (written by the
Object
constructor) to their initial values. Since neither