Java, visibility and infinite loop occurrence

谁都会走 提交于 2020-05-23 16:03:28

问题


I'm studying Java Concurrency in Practice and there it is explained why the following snippet of code is bad:

public class NoVisibility {
    private static boolean ready;
    private static int number;
    private static class ReaderThread extends Thread {

      public void run() {
      while (!ready) {
        Thread.yield();
        System.out.println(number);
      }
    }

    public static void main(String[] args) {
       new ReaderThread().start();
       number = 42;
       ready = true;
   }
}

This code may print 0 or loop forever. While it is easy to understand why NoVisibility could print 0 instead of 42 (due to re-ordering issue), I'm a little confused about the infinite loop.

What is a practical scenario where an infinite loop may occurr, in this code?


回答1:


The loop stops when ready is set to true. And ready is set to true by the main thread. But since the ready field is not volatile, the looping thread might continue to see a cached value: false.

The volatile keyword guarantees that all the threads reading a volatile field will actually see the last value stored in this field by any other thread. Without volatile, you don't have this guarantee.




回答2:


Well, it turns out that things are not nearly that easy: as you print in the cycle, you synchronize on the output streams, and that involves all the memory fences, so you will actually exit.

Now, you must not rely on such a behaviour, but that means if you're going to demonstrate the problem, you should be extra careful: many system calls, especially I/O, will involve hidden synchronization which can ruin a trick. So you end up saying, "that's baaaaad"— and being not able to prove that, which is a bit frustrating.

For a code example, check out illustrating volatile : is this code thread-safe? (sorry for a shameless plug—it's just that I only have this code there).




回答3:


Please see the below code, It introduces the Infinite loop pretty on x86. Tried with jdk8 and jdk7

package com.snippets;


public class SharedVariable {

    private static int  sharedVariable = 0;// declare as volatile to make it work
    public static void main(String[] args) throws InterruptedException {

        new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                sharedVariable = 1;
            }
        }).start();

        for(int i=0;i<1000;i++) {
            for(;;) {
                if(sharedVariable == 1) {
                    break;
                }
            }
        }
        System.out.println("Value of SharedVariable : " + sharedVariable);
    }

}

Trick is not to expect the processor to do the reordering rather make compiler to make some optimization which introduces the visibility bug.

If you run the above code you will see it hangs indefinitely because it never sees the updated value sharedVariable.

To correct the code declare the sharedVariable as volatile.

Why normal variable didn't work and the above program hangs ?

  1. sharedVariable was not declared as volatile.
  2. Now because sharedVariable was not declared as volatile compiler optimizes the code. It sees that sharedVariable is not going be changed so why i should read from memory every time in the loop. It will take the sharedVariable out of the loop. Something similar to below.

    for(int i=0i<1000;i++)/**compiler reorders sharedVariable
    as it is not declared as volatile
    and takes out the if condition out of the loop
    which is valid as compiler figures out that it not gonna  
    change sharedVariable is not going change **/
      if(sharedVariable != 1) {  
        for(;;) {}  
      }      
    }
    

Shared at github : https://github.com/lazysun/concurrency/blob/master/Concurrency/src/com/snippets/SharedVariable.java



来源:https://stackoverflow.com/questions/8768364/java-visibility-and-infinite-loop-occurrence

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!