开发者

Infinite loop problem with while loop and threading [duplicate]

This question already has an answer here: Loop doesn't see value changed by other thread without a print statement (1 answer) Closed 8 years ago.

Using a basic example to illustrate my problem I have 2 near-identical bits of code.

This code causes the while loop to run infinitely.

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;
}

This code however (i.e. doing something in the while loop) causes the loaded variable to be successfully evaluated and allows the while loop to break and method to finish.

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;
}

Can anyone explain to me why开发者_JAVA技巧 this is?


The first loop only "appears" to run infinitely. You're actually running an "active wait", burning 100% of your CPU, such that your OS or JVM can't make a context switch and let the other thread run.

With the System.out.println() on the other hand, there is I/O involved, resulting in a somewhat "inactive wait". The OS or JVM can switch contexts and the other thread starts.

If you'd run your first program for 10 hours, I'm sure the loop would break eventually


Check that 'loaded' is definitely declared as volatile.

Explanation: if a variable is read and/or written by multiple threads, then you need to take appropriate thread-safety measures. One such thread-safety measure is volatile, which is suitable for primitive values (or object references) which are read or written as 'simple' actions with the value written on a given occasion not depending on the previously read value. For more information, I have an article about volatile on my web site (along with other information about thread-safety generally) that may be of help.


If loaded is not volatile, the JIT is free to optimise it by placing it in a register and not loading it from memory every time. In the second case, the loop is too complex for the JIT to assume it doesn't need to load loaded each time.

Note: its is the JIT not the javac compiler which optimises the code.


Read up on Memory Consistency Errors. Basically, different threads have inconsistent views of what should be the same data. In order to resolve this, read up on Synchronization. Or simply declare loaded as volatile, since its value is only being written by a single thread.


I believe you are experiencing a Busy Wait with the empty loop, which will never sleep. Thus, your Thread to set loaded to true never runs.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜