I’ve been reading up on Java concurrency and had forgot the fact that synchronization blocks in two threads using the same lock also affect the visibility of variables, even though they were not defined as “volatile”. If I have code like this
Object lock = new Object();
boolean a = false, b = false, c = false;
void threadOne() {
a = true;
synchronized(lock) {
b = true;
}
c = true;
}
void threadTwo() {
while (true) {
synchronized(lock) {
if (a && b && c) break;
}
}
}
… and threadOne and threadTwo will be called by different threads:
-
Is it guaranteed that the code will break out of the while loop?
-
What if we remove variable c out of the equation? I’m wondering if only b is guaranteed to be visible in threadTwo because it was inside the synchronization block.
No. The Java memory model is defined in terms of “happens before” relationships:
The spec goes on to say:
where
hbstands for happens-before, andAlso note that:
So in your example, the
synchronized(lock)aroundbwill establish a happens-before relationship for the following read, and thus the value ofbis guaranteed to be visible in other threads that also usesynchronized(lock). Explicitly,Similarly,
awill be guaranteed to be visible to the other thread. Explicitly,The write and then subsequent read of
cdoes not have a happens-before relationship, so therefore, according to the spec, the write tocis not necessarily visible tothreadTwo.Yes, see above.