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并发编程上写着可能 一直循环或输出0   输出0 我理解  一直循环是为什么啊   主线程和分出的线程不是会一起执行吗 ,那ready应该会为true的啊

解决方案 »

  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;
    }
    }
    如果while (ready) ready是true的话会永远执行,进入死循环
      

  2.   


    当主线程把ready改为true之后,分线程就会终止。但并发运行意味着你无法预测在主线程把ready改为true之前分线程已经执行了多少次循环。
      

  3.   

    while (ready) 也不一定是死循环,主线程对ready 的赋值 和while(ready)两个执行顺序是随机的
    尽管是随机的 但无论如何 ,最后ready都会为true 那书上为什么说还会进入死循环 求解
      

  4.   

    书上的意思是Java内存模型不保证在没有使用同步的情况下,一个线程修改了某个变量,另一个线程就一定能看到这种修改也就是说main线程修改了ready,你new出来的那个线程不一定能看到ready已经被改掉了
    但是,这与操作系统,CPU,JVM的实现等都是密切相关的想看到死循环这种结果是很难的,尤其是在sun hotspot虚拟机的-client模式下,更是比买彩票中一个亿的几率还小,但这是没有任何保证的,所以为确保不会出现那亿分之一的可能性,就要用同步
      

  5.   

    但两个线程读的是同一块内存, 在反复判断whlie(!ready) 迟早会读到 ready为true吧,难道会看不到?
      

  6.   

    CPU是有缓存,java memory model允许不同的线程将变量读进cpu缓存以提升性能,这就带来了cpu缓存里的值什么时候刷回内存的问题,如果没有使用同步,允许cpu cache里的值永远不刷回内存
      

  7.   

     我觉得应该是volidate的问题 而不是同步的问题
     因为主线程修改ready的目的就是给另一个线程看的,另一个线程只是读取ready,而且是作为标志使用
      

  8.   

    先执行主线程的啊,一般主线程执行完毕后才会开始执行子线程。即是热read在子线程执行前就已经是true了
      

  9.   

    在这个例子中可以使用volatile来达到可见性的要求但volatile在jdk1.4中的语义不够强,滥用volatile使分析代码变得困难,是存在一些问题的
      

  10.   

    子线程
    while{!ready)
      Thread.yield();
    运行完之后一定是ready=true;
    而此时主线程已经运行了number=42,从而保证子线程打印System.out.println(number);的结果一定是主线程赋值number为42后的值