JAVA并发编程实战里的一个例子

新手上路,请多包涵

在看到这本书的第三张的第一个程序例子的时候产生了一些疑问,希望大牛能够帮忙解惑,小弟不胜感激。例子如下:

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

疑惑

作者在后面写到“NoVisiabilty可能会持续循环下去,因为读线程可能永远都看不到ready的值” 为什么呢?在我的理解当中肯定是会停止的呀,有没有可能是书中写错了呢。

阅读 4.7k
7 个回答

我看书里好像是这样, 你这里貌似加了个大括号在while这块(不过不影响), 我大概理解了你的困惑:

现在程序中有2个线程, 一个是main, 一个是 ReaderThread;
由于没有同步, 就存在这样一种可能: ReaderThread先启动执行了, 而且马上进入run(), 这个时候main有可能执行了下面的两个赋值, 也有可能还没有, 好了, 我们假设第二种: 还没有;
此时while(true) 就开始无限循环Thread.yield()--> 这是有可能的, 因为 yield让权了可能马上又开始执行; 而由于没有对ready做任何同步, 在ReaderThread中读取的ready可能一直都没有从主存中同步, 这样就陷入了死循环;
这是小的几率, 但是也是可能的存在;
所以书里会那么说; 不知道我说明白了没有[捂脸]
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内存模型就差不多能理解了 书里写的没问题

简单来讲就是主线程修改了readyReaderThread不知道。还以为是false

线程有自己的工作内存空间, 其他线程改了 ready, 你自己线程空间可能没改.

内存可见性问题,去看看JMM

两个方面吧
一个是内存可见性,子线程看到的ready值和主线程的可能不一致。
另一个是每次Thread.yield()之后,还是子线程抢到了执行权。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题