I recently read http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html , which clearly describes many features of the Java memory model. One particular passage received 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.
It seems obvious to me, however, after reading http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html and before that, before the definition, all I could find about unlocking the monitor was this is when one thread unlocks the monitor, which happens, before another thread blocks it again (which also makes sense). Can someone explain how JLS explains the obvious condition that all actions in the synchronization block must happen - before the unlock operation?
FURTHER COMMENTS:
Based on a few answers, I wanted to write additional comments on what you guys said:
- Single-threaded relocation
A few "truths" from the source I cited:
a = new A()
if it new A()includes one hundred operations followed by assignment of the address on the heap before a, the compiler can simply change the order of the heap address assignment to a, and then follow the usual initialization (problem from double checked lock)
synchronized{
a = 5;
}
print a;
can be changed to
synchronized{
a = 5;
print a;
}
SO we reorder monitorexitwith a print statement (also valid according to JLS)
Now, the simple case I talked about:
x = 1;
y = 2;
c = x + y;
print c;
, x first y. , , x , y. , .
, "" , ,
synchronized{
a = 5;
print a;
}
, :
synchronized{
a = 5;
}
print a;
, YET, , JLS ( ). , - JLS ? , " " , , "" .