while循环和线程的无限循环问题

时间:2011-07-12 13:11:49

标签: java multithreading while-loop infinite-loop

使用一个基本的例子来说明我的问题,我有2个几乎相同的代码。

此代码导致while循环无限运行。

private boolean loadAsset() {
    new Thread(new Runnable() {

        @Override
        public void run() {

            // Do something
            loaded = true;

        }
    }).start();

    while (!loaded) {
        // System.out.println("Not Loaded");
    }
    System.out.println("Loaded");
    return false;
}

然而,这段代码(即在while循环中执行某些操作)会导致成功评估loaded变量,并允许while循环中断并完成方法。

private boolean loadAsset() {
    new Thread(new Runnable() {

        @Override
        public void run() {

            // Do something
            loaded = true;

        }
    }).start();

    while (!loaded) {
        System.out.println("Not Loaded");
    }
    System.out.println("Loaded");
    return false;
}

任何人都可以向我解释为什么会这样吗?

5 个答案:

答案 0 :(得分:7)

第一个循环仅“出现”无限运行。您实际上正在运行“活动等待”,烧掉100%的CPU,这样您的操作系统或JVM就无法进行上下文切换而让另一个线程运行。

另一方面,System.out.println()涉及I / O,导致稍微“无效等待”。操作系统或JVM可以切换上下文,另一个线程启动。

如果您运行第一个程序10个小时,我确信循环最终会破坏

答案 1 :(得分:6)

检查'loaded'是否明确声明为volatile。

说明:如果多个线程读取和/或写入变量,则需要采取适当的线程安全性度量。一种这样的线程安全措施是易失性的,它适用于原始值(或对象引用),它们被读取或写为“简单”动作,在给定的场合写入的值不依赖于先前的读取价值。有关更多信息,我在我的网站上有一篇关于volatile的文章(以及有关线程安全的其他信息)可能会有所帮助。

答案 2 :(得分:4)

如果loaded不是易失性的,JIT可以通过将其放入寄存器而不是每次都从内存加​​载来自由优化它。在第二种情况下,循环过于复杂,JIT不必假设每次都不需要加载loaded

注意:它是JIT而不是优化代码的javac编译器。

答案 3 :(得分:2)

阅读Memory Consistency Errors。基本上,不同的线程对于应该是相同数据的内容具有不一致的视图。要解决此问题,请阅读Synchronization。或者只需将loaded声明为volatile,因为它的值仅由单个线程写入。

答案 4 :(得分:0)

我相信你正在遇到一个Busy Wait空循环,它永远不会睡觉。因此,您设置加载到true的线程永远不会运行。