I am refering to page 261 – 262 of Joshua Bloch Effective Java
// Properly synchronized cooperative thread termination
public class StopThread {
private static boolean stopRequested;
private static synchronized void requestStop() {
stopRequested = true;
}
private static synchronized boolean stopRequested() {
return stopRequested;
}
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!stopRequested())
i++;
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
requestStop();
}
}
Note that both the write method
(requestStop) and the read method
(stop- Requested) are synchronized. It
is not sufficient to synchronize only
the write method! In fact,
synchronization has no effect unless
both read and write operations are
synchronized.
Joshua’s example is synchronized on this. However My doubt is that, must synchronized be acted on the same object? Say, if I change the code to
private static void requestStop() {
synchronized(other_static_final_object_monitor) {
stopRequested = true;
}
}
private static synchronized boolean stopRequested() {
return stopRequested;
}
will this still able to avoid liveness failure?
That’s is, we know grabbing monitor for a same object during read/write can avoid liveness failure (According to Joshua Bloch’s example). But how about grabbing monitor for different object during read/write?
I don’t believe it’s guaranteed, although I wouldn’t be surprised if it actually was okay in all existing implementations. The Java Language Specification, section 17.4.4 states this:
I believe that all the safety of reading/writing shared variables within locks stems from that bullet point in the spec – and that only specifies anything about a lock and an unlock action on a single monitor.
EDIT: Even if this did work for a single variable, you wouldn’t want to use it for multiple variables. If you update multiple variables while holding a monitor and only read from them when holding a monitor, you can ensure that you always read a consistent set of data: nothing’s going to write to variable Y before you’ve read that but after you’ve read variable X. If you use different monitors for reading and writing, that consistency goes away: the values could be changed at any time while you’re reading them.