我指的是 Joshua Bloch Effective Java 的第 261 - 262 页
// 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();
}
}
Joshua 的示例在
this
上同步。但是我的疑问是,synchronized
必须作用于同一个对象吗?说,如果我将代码更改为 private static void requestStop() {
synchronized(other_static_final_object_monitor) {
stopRequested = true;
}
}
private static synchronized boolean stopRequested() {
return stopRequested;
}
这还能避免活性失败吗?
也就是说,我们知道在读/写期间为同一个对象抓取监视器可以避免活性失败(根据 Joshua Bloch 的例子)。 但是如何在读/写期间抓取不同对象的监视器呢?
最佳答案
我不相信这是有保证的,尽管如果在所有现有实现中它实际上都可以,我也不会感到惊讶。 Java 语言规范 section 17.4.4 指出:
我相信在锁中读/写共享变量的所有安全性都源于规范中的那个要点 - 并且只指定了关于单个监视器上的锁定和解锁操作的任何内容。
编辑:即使这确实适用于单个变量,您也不希望将它用于多个变量。如果您在持有监视器时更新多个变量并且仅在持有监视器时从它们读取,您可以确保您始终读取一组一致的数据:在您读取之前没有任何内容会写入变量 Y,但在您读取之后读取变量 X。如果您使用不同的监视器进行读取和写入,那么一致性就会消失:在您读取值时可以随时更改这些值。