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;
    }
}
在《java concurrency in practice》3章1节 中描述说上面的代码有可能 不会有输出,或者,有可能输出为0,又或者按照我们一般期待的那样输出,但是我在自己机器上实践这些代码时,怎么都无法出现书中所描述的问题。一直很正常。
我如何才能产生书中所描述的 现象

解决方案 »

  1.   

    这与 Java 的内存模型有关。更改 ready 值的线程与作为判断条件的线程并不是同一个线程。也就是说,主线程将 read 更改为 true,那在 ReaderThread 并不会立即看到 read 变为了 true,可能要过好长时间才能看见。Java 中的每个线程都有一块自己独立的空间,为了提高运行效率,会将共享变量的值复制一份过来,并不会每次读取变量值时都从共享区中去读取。如果共享变量 synchronized 同步的话,那表示每次都从共享区中获取值。针对于目前这段代码,没有必要加什么同步,只需要把private static boolean ready;改为  private static volatile boolean ready;
      

  2.   

    不过使用 volatile 的更改需要在 JDK 5 及以上的版本有效,JDK 5 以下的版本无效。
      

  3.   

    这个程序正常运行完,我也看不出 会没有输出或输出为0. 主线程运行到这里new ReaderThread().start();时间片用完,就启动了子线程,子线程一直在循环,这时侯这个程序异常死了,没输出,哈哈输出为0,看不出,望有高手再回答
      

  4.   


    这个java内存模型 有没办法来测试呢?有了这个内存模型,这个程序就有解了。
      

  5.   


    不好意思,这个证明及测试已经超出我的能力范围了。给你个专门的 JMM 页面吧。
    http://www.cs.umd.edu/~pugh/java/memoryModel/
      

  6.   

    没有输出不好理解,这个貌似和java的内存模型没什么关系吧。输出0倒确实因为内存模型。
      

  7.   

    new ReaderThread().start();并不是马上执行线程的 而是准备执行吧我个人认为主要是因为:Thread.yield();
    他让CPU执行new ReaderThread().start();下面的语句:
    number = 42;
    ready = true;
    如果你改为
        private static class ReaderThread extends Thread {
            public void run() {
                while (!ready)
                    //Thread.yield();
                System.out.println(number);
            }
        }    public static void main(String[] args) throws Exception{
            new ReaderThread().start();
    Thread.sleep(1);//
            number = 42;

            ready = true;
        }如果你sleep一毫秒 并且没有yield。那么线程就会输出一个零
    如果加上yield那么就会执行sleep(),number=42,ready=true 
    然后输出number:42
      

  8.   

    需要让ready和number不及时共享才能测试