《Java并发编程实战》一段代码的疑惑

《Java并发编程实战》3.1节的一段代码:

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

按照书中所讲,这段代码不一定输出42,有可能陷入死循环。原因是代码中没有足够的同步机制,无法保证主线程写入的ready他number对读线程是可见的。也有可能是0,原因是“重排序”,读线程看到了主线程写入的ready却没有看到number。但是经过多次测试,始终输出42,既没有输出0,也没有死循环。为了验证书中所说的主线程修改对读线程不可见,我改写了代码:

public class NoVisibilityLoop {

    private static int number;
    
    private static class ReaderThread extends Thread {
        public void run() {
            while (true) {
                System.out.println(number);
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                }
            }
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        new ReaderThread().start();
        Thread.sleep(1000);
        number = 42;
    }
}

多次测试输出结果是:
0
0
0
0
0
42
42
42
42
这个结果说明了主线程写入的number对读线程是可见的。但是这本书的作者一堆大牛,不会搞错的。还请大家帮忙看看我的验证方法哪里出问题了,谢谢。
运行环境:jdk 1.8.0_101,server模式。

萧十郎
浏览 515回答 4
4回答

慕斯王

原文的意思是让你重复多次运行这段代码大概运行几十次甚至上百次,可能出现一次死循环,而这个在实际开发中是不可取的 而这是代码设计缺陷的问题,所以建议不要这么编程,要保持主副线程的同步性不要用这样的写法,你继续往后看,这书既然这么说,可能会有别的解决方案来帮你理解他描述的原理

慕桂英3389331

首先测试多次正确也不能保证完全就是正确的,其次这本书是jdk5和6了,jdk8估计做了些优化, private static boolean ready; private static int number; private static class ReaderThread extends Thread { @Override public void run() { int i=0; while (!ready) { i++; // Thread.yield(); } System.out.println(number); } } public static void main(String[] args) throws Exception { new ReaderThread().start(); TimeUnit.MILLISECONDS .sleep(9); number = 42; ready = true; } 把 thread.yield 换成 i++ 或者 sleep 与否 结果都有差别这种执行顺序是指令重排决定的,不用volatile没法保证

POPMUISE

应该是JDK版本差异造成的
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java