Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 带while循环和线程的无限循环问题_Java_Multithreading_While Loop_Infinite Loop - Fatal编程技术网

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

Java 带while循环和线程的无限循环问题,java,multithreading,while-loop,infinite-loop,Java,Multithreading,While Loop,Infinite Loop,用一个基本的例子来说明我的问题,我有两个几乎相同的代码位 此代码导致while循环无限运行 private boolean loadAsset() { new Thread(new Runnable() { @Override public void run() { // Do something loaded = true; } }).start(); while (

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

此代码导致
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循环中执行某些操作)会导致成功计算加载的
变量,并允许
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;
}

有人能解释一下为什么会这样吗?

请仔细阅读。基本上,不同的线程对什么应该是相同的数据有不一致的看法。要解决此问题,请仔细阅读。或者简单地将
loaded
声明为
volatile
,因为其值仅由单个线程写入。

检查“loaded”是否明确声明为volatile

说明:如果变量由多个线程读取和/或写入,则需要采取适当的线程安全措施。一个这样的线程安全度量是volatile,它适用于原语值(或对象引用),原语值作为“简单”操作读取或写入,并且在给定情况下写入的值不取决于先前读取的值。关于更多信息,我在我的网站上有一篇关于线程安全的文章(以及其他关于线程安全的一般信息),可能会有所帮助。

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

另一方面,使用
System.out.println()
时,会涉及I/O,导致某种程度上的“非活动等待”。操作系统或JVM可以切换上下文,其他线程启动


如果第一个程序运行10个小时,我确信循环最终会中断。如果加载的
不是易失性的,JIT可以通过将其放入寄存器而不是每次从内存加载来优化它。在第二种情况下,循环太复杂,JIT无法假设它不需要每次加载
loaded


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

我相信您正在经历一个空循环,它永远不会休眠。因此,要将loaded设置为true的线程永远不会运行

为什么您依赖一个可以被其他字段更改的字段值?您可能需要在块同步的情况下使整个块保持良好状态。我没有意识到…@Peter Lawrey,缓存是由CPU控制的而不是JIT,我认为
加载的
可能会在缓存已满时被丢弃,然后再次从内存加载。请参阅。事实上,JIT将while循环优化为无限循环,请参阅。对,但没有解释?嗯……哦,好吧对不起,我添加了一个解释。