所以,前几天我做了一个分形绘图程序,当它变得太慢时,我想我会通过多线程来加快它的速度。所以我介绍了几个线程,每个线程绘制一部分图像。要知道我何时完成了线程,我引入了两个变量AMOUNT_OF_THREADS
和threadsDone
。我创建了AMOUNT_OF_THREADS
个线程,每个线程都绘制了自己的分区,并在完成后增加threadsDone
。在主要方法中,我放入
while (threadsDone < AMOUNT_OF_THREADS)
;
令我惊讶的是,循环从未完成循环。我知道它,因为每个线程打印出"Thread done"
,当主方法循环完成时,它应该打印出"Main done"
但它没有。我试图打印threadsDone < AMOUNT_OF_THREADS
,现在循环停止了。怪异。
我做了一些进一步的测试,这个问题似乎只发生在线程运行> 2ms或每次循环时循环花费> 2ms时才会发生。有时,当线程运行2ms时会发生此错误。
我怀疑打印功能使循环运行时间> 2毫秒,这使我在打印出值时起作用,但我仍然想知道为什么会这样。
所以我的问题是,为什么会发生这种情况?它是编译器/ JVM中的错误还是其他任何错误?我问我的父亲,他在思考了几分钟之后回复说它必须是while循环运行得太快,但他不确定。
以下是一些存在此问题的代码示例:
public class WhileThread {
public static boolean threadDone = false;
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
threadDone = true;
System.out.println("Thread done.");
}
}).start();
while (!threadDone) {
}
System.out.println("Main program done.");
}
}
当您将Thread.sleep
中的0更改为10时,此错误永远不会发生。
如果重要,我使用带有Java SE 8的Macbook Air。
答案 0 :(得分:1)
所以我的问题是,为什么会发生这种情况?它是编译器/ JVM中的错误还是其他任何错误?
这不是一个错误,它是一个刻意的设计决定。为了使这样的代码可靠地运行,JVM必须假设任何线程都可以随时更改任何变量,除非它们能够证明这不可能发生。这会抑制各种非常有价值的优化,并使Java代码运行得慢得多。
相反,明确允许这些优化,并添加了几个方法(volatile
,synchronized
等),以允许编码器显示变量可以由其他线程更改其值的位置。 / p>