Let me try to answer with an example. Let us say, we have original code like this:
synchronized(this) {
a();
b();
}
c();
synchronized(this) {
d();
e();
}
It would be unsafe (in general) to transform the above code to synchronized(this) {
a();
b();
c();
d();
e();
}
Simply because Compiler does not know (again, in general) what may happen during the execution of c(). However, the following transformation is safe (the timing behavior changes, but as you point out, that is not a guarantee programmers should expect). synchronized(this) {
p();
q();
}
synchronized(this) {
r();
s();
}
to synchronized(this) {
p();
q();
r();
s();
}
since there is nothing happening between the two synchronized sections.For the for loop, an example of code where pulling the synchronized statement out of the loop is problematic:
for(a = AcquireLock(), c = 0; c < 100; c++) {
synchronized(this) {
f();
}
}
ReleaseLock(a);
I don't think it is safe to transform to a = AcquireLock();
synchronized(this) {
for(c = 0; c < 100; c++) {
f();
}
}
ReleaseLock(a);
Perhaps you (and the original blog post) assume we are only talking about movement of code after ensuring that such movement is safe, but it was not clear from the document.