I have recently read http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html which clearly describes a lot of intrinsics of Java memory model. One particular excerpt got my attention namely:
The rule for a monitorexit (i.e., releasing synchronization) is that
actions before the monitorexit must be performed before the monitor is released.
Seems obvious to me, however having read http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html and happens-before definition, all I could find about the monitor unblock is when one thread unlocks the monitor that happens-before the other thread locking it again (which makes perfect sense as well). Could someone explain how JLS explains the obvious condition that all the actions within the synchronization block must happen-before the unlock operation?
FURTHER COMMENTS:
Based on a couple of responses I wanted to write up further comments to what you guys have been saying:
- Reodering within a single-thread
A couple of "truths" from the source I cited:
a = new A()
if new A()
involves a hundred operations, followed by assignment of address on a heap to a
, compiler can simply reorder those to assign the heap address to a
and then follow the usual initialization (problem from double checked locking)
synchronized{
a = 5;
}
print a;
can be changed to
synchronized{
a = 5;
print a;
}
SO we reordered monitorexit
with print statement (also valid according to JLS)
Now, the simple case I mentioned:
x = 1;
y = 2;
c = x + y;
print c;
I see no reason that stops a compiler from either assigning x first or y first. There is completely nothing stopping it, as the final output is unchanged regardless of whether x is assigned first or y is. So the reordering is perfectly possible.
- monitor.unlock
Based on the example with print statement being "pulled into" the synchronization block, let's try to reverse this i.e. startwing with
synchronized{
a = 5;
print a;
}
I could expect the compiler to do this:
synchronized{
a = 5;
}
print a;
Seems perfectly reasonable within the single-threaded world, YET this is definitely invalid, and against JLS (according to the cited source). Now why is that the case, if I cannot find anything within the JLS about this? and clearly the motivation about the "order of the program" is now irrelevant, since the compiler can make reoderings such as "pulling in" the statements to the synchronized block.