[concurrency-interest] Question about "happens-before"
jmanson at cs.purdue.edu
Fri May 19 11:51:35 EDT 2006
Robert Kuhar wrote:
> I asserted that they had two problems with this code. As I understand it, the
> runtime is free to reorder the instructions in this constructor. This means
> that initialized=true may occur before the calls to either securityCheck() or
> init(). If that is the case, its value cannot be trusted as this code stands
This is not the case. In Java, exceptions are precise, and must be
treated like control flow. The write will only occur if the exception
is not thrown. Neither this thread nor any other can see a write that
does not occur. This is one of those very few, tricky to get,
guarantees for programs with data races that we make.
So, the point that the speaker was probably trying to make, which is
that you can check the value of "initialized" to determine if
securityCheck() exited without throwing an exception, is perfectly valid.
The compiler is free to move the write to initialized early if it can
determine that the exception will not be thrown. It is also free to
hoist it above the call to init() (depending on what init() actually
does). This means that if another thread can obtain a reference to this
object via a data race, and reads the "initialized" variable, it can see
the value "true" even if the object is not fully constructed.
Alternatively, such a thread could see a value "false" for initialized
even if the object is fully constructed.
A few things to note:
0) Why isn't this class final?
1) As has been noted, constructors are guaranteed to happen-before
finalize methods. Therefore, finalizers will see all the writes that
occur in the constructor. For the purposes of whether this code does
what it is intended to do, though, this is irrelevant, because the
finalizer (I assume) is just resurrecting the object.
2) The initialized field should probably be final (which would mean that
you could not put the "initialized = false" line in, but you probably
don't want that line there anyway, as the default value is false, and
moving the constructor around / adding more constructors will cause
confusion). Otherwise, you could use reflection to set it.
More information about the Concurrency-interest