在《Effective Java》一书中:
上述代码来自于《Effective Java》一书,在该书中使用了
// Broken! - How long would you expect this program to run?
public class StopThread {
private static boolean 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);
stopRequested = true;
}
}
背景线程不会在一秒钟后停止。这是因为JVM中的优化——hoisting(提升)。HotSpot服务器VM会进行此优化。
您可以在以下主题中查看:
为什么HotSpot会使用hoisting进行优化?
此优化的过程如下:
if (!done)
while (true)
i++;
有两种方法可以解决这个问题。
1. 使用 volatile
private static volatile boolean stopRequested;
volatile的作用是:
- 禁止变量提升(hoisting)
- 保证任何读取该字段的线程都能看到最近写入的值
2. 使用synchronized
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();
}
}
上述代码来自于《Effective Java》一书,在该书中使用了
volatile
修饰符来替代stopRequested
变量。private static boolean stopRequested() {
return stopRequested;
}
如果这个方法省略了synchronized
关键字,那么程序不会正常工作。
我认为这个改变会导致synchronized
关键字的提升问题。
这样说对吗?
volatile
或synchronized
也会禁止提升 (hoisting
)?如果不是,这个程序能运行正确吗? - Edward