网易的一道java笔试题,不甚明白是何居心,求大神讲解
package netease;public class VolatileTest { private static int number;
private static boolean ready;

private  static class ReadThread extends Thread{
public void run(){
while(!ready)
Thread.yield();
System.out.println(number);
}
}
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
new ReadThread().start();
number = 42;
ready = true;
}}1) 上面的代码输出什么,并说明原因?
2)若ready是volatile修饰,输出什么,说明原因?

解决方案 »

  1.   

    Java 理论与实践: 正确使用 Volatile 变量
      

  2.   

    可能会死循环,打印出0或者42
    也可能啥都没打印
    ……http://www.ticmy.com/?p=5http://www.ticmy.com/?p=118
      

  3.   

    http://topic.csdn.net/u/20120911/22/61a34a6d-13da-4f0a-b05c-02c996fa39a0.html同样的题
      

  4.   

    42  
    ReaderThread线程的Thread.yield()方法使得main主线程优先使用CPU,不会导致ReadThread().start()后CPU被独占而使main的number = 42;ready = true;等无法执行。因此,ReaderThread线程的while循环有限次后(次数不定)ready = true;停止循环并输出42由于main执行时间太短,楼主代码还看不出Thread.yield()方法“让步”的情况,稍微改了下,可运行看看(每次的结果都不一样)public class test4 {
        private static boolean ready;
        private static int number;
        
        private static class ReaderThread extends Thread
        {
            public void run()
            {
             int j=0;
                while(!ready)
                {
                 System.out.println("ReaderThread-out-"+j);
                    Thread.yield();
                    j++;
                }
                System.out.println(number);
            }
        }
        /**
         * @param args
         * @throws InterruptedException 
         */
        public static void main(String[] args) throws InterruptedException {
            // TODO Auto-generated method stub
            new ReaderThread().start();
            number = 42;
            for(int i=0;i<1000;i++){
             System.out.println("main-out-"+i);
            }
            ready = true;
        }
    }
      

  5.   

    1.可能是0可能是42可能是什么都没打印。
    2.加不加volatile修饰符没什么影响,最多是0或者42打的少一点
      

  6.   

    我觉得不会死循环的后面有ready = true;
    只是迟早的事情
      

  7.   

    你试了并不表示它一直就那样运行都是因为可见性和指令重排序问题,main线程修改number和ready(都是非volatile的且未同步),那么ReadThread究竟能不能看到这种修改呢?jvm是没有保证的,可能出现一下情形:
    1、ReadThread看到了number为42,ready为false
    2、ReadThread看到了number为0,ready为false
    3、ReadThread看到了number为42,ready为true
    4、ReadThread看到了number为0,ready为true还要加两种:
    1、main线程执行结束了,ReadThread线程还没开始
    2、ReadThread线程执行结束了,main线程的赋值还没做
      

  8.   

    java定义了一种内存模型,也就是Java Memory Model,所有jvm最低要实现该模型,但可以比这个模型更高。什么概念?也就是说在jvm1实现上运行没问题(就像这里的这个程序一样,未充分同步(包括volatile和synchronized)),可能是因为凑巧,可能是因为jvm1实现的时候高于JMM;如果将此程序放到仅实现了JMM的最低要求,那么程序就有问题了。为什么要定义JMM,一为并发效率(每次都访问内存是非常低效的,CPU的缓存,寄存器更高效);二为跨平台(每个平台内存与CPU的缓存,寄存器之间的同步时机)JMM就是规定了多线程下什么时候需要重新将内存中的数据读取到工作缓存,什么时候要将工作缓存中的数据写回内存
      

  9.   

    42是正解,因为不管线程yield让出多少次,总归是要让出去的。然后执行number = 42,之后打印出来。
      

  10.   

    学习了 Volatilehttp://qingfeng825.iteye.com/blog/152269最终看这篇文章看懂了原理
      

  11.   

    打印出42,我认为这个题目有两个知识点,第一个是类的初始化过程,第二个是线程的让步
    new ReadThread().start();这句话其实可以分成两句
    ReadThread th=new ReadThread(); ---1
    th.start();            ---2
    这样大家就好理解了,执行第一句时,会执行类的初始化。由于ready和number为静态变量,他们会在类初始化时也被初始化,所以相当于这样 
    private static boolean ready;
      private static int number;
    public ReadThread(){
     number = 42;
    ready = true;
    } 这样以后再执行th.start();大家可以去网上搜下JAVA中关于类的初始化和类的加载放面的知识
      

  12.   

    附带的测试程序:package com;
    public class VolatileTest { private static int number;
    private static boolean ready; private static class ReadThread extends Thread{
    public void run(){
    System.out.println("while1"+ready);
    System.out.println("while2"+number);
    while(!ready)
    Thread.yield();
    System.out.println("让步后1"+ready);
    System.out.println("让步后2"+number);
    }
    }
    public static void main(String[] args) throws InterruptedException {
    System.out.println(number);
    System.out.println(ready);
    ReadThread th=new ReadThread();
    System.out.println("MAIN"+number);
    System.out.println("main"+ready);
    th.start();
    number = 42;
    System.out.println("何时执行");
    ready = true;
    } }
     
    控制台输出:
    0
    false
    MAIN0
    mainfalse
    何时执行
    while1true
    while242
    让步后1true
    让步后242
      

  13.   

    如果不加 volatile,可能打出 0 或者 42
    如果加volatile, 只能打出42因为volatile 关键字有一个作用是 禁止指令重排序优化,就是java 内存模型中所描述的 Within Thread As If Serial Semantics