synchronized(this) {
a = AcquireLock();
for(c = 0; c < 100; c++) {
f();
}
}
ReleaseLock(a);
which is inline with what the blog post was proposing. for (...) {
synchronized (obj) {
// something
}
}
…could it optimize into this? synchronized (this) {
for (...) {
// something
}
}
My answer to that is in general, no. import java.util.concurrent.locks.ReentrantLock;
class X {
private static ReentrantLock aL = new ReentrantLock();
private static ReentrantLock bL = new ReentrantLock();
static int x = 0;
static int c = 0;
static public void main(String[] args) {
for(aL.lock(); c < 100; c++) {
synchronized(bL) {
x = x + 0x42;
}
}
aL.unlock();
}
}
If I understood it right, the blog post was asking a question whether JVM can transform this to: import java.util.concurrent.locks.ReentrantLock;
class X {
private static ReentrantLock aL = new ReentrantLock();
private static ReentrantLock bL = new ReentrantLock();
static int x = 0;
static int c = 0;
static public void main(String[] args) {
synchronized(bL) {
for(aL.lock(); c < 100; c++) {
x = x + 0x42;
}
aL.unlock();
} // end synnchronized
}
}
Since the locks are now acquired in a different order, does that not qualify as observable behavior? 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(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.
Because '...' can include arbitrary side-effect inducing statements that can't be moved around without affecting the behavior. As the poster discovered.