网易的一道java笔试题

孤雲獨去閑 2012-10-11 01:19:46
网易的一道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修饰,输出什么,说明原因?
...全文
882 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
eiermkor 2013-08-26
  • 打赏
  • 举报
回复
17L是正解! 虽然跑了很久都没跑出0来 但理论上讲确实是会跑出0来的
liangchengfck1 2012-10-12
  • 打赏
  • 举报
回复
原来你就是42啊 终于找到你了
hheeyyii 2012-10-11
  • 打赏
  • 举报
回复
我觉得不会死循环的

后面有ready = true;
只是迟早的事情
名字到底多长 2012-10-11
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]

可能会死循环,打印出0或者42
也可能啥都没打印
……

http://www.ticmy.com/?p=5

http://www.ticmy.com/?p=118
[/Quote]
为什么是0或者死循环啊。。。我试了个循环都是42啊。。。。。
hheeyyii 2012-10-11
  • 打赏
  • 举报
回复
1.

可能是0可能是42可能是什么都没打印。


2.加不加volatile修饰符没什么影响,最多是0或者42打的少一点
KelvenCheung 2012-10-11
  • 打赏
  • 举报
回复
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;
}
}
杀手 2012-10-11
  • 打赏
  • 举报
回复
http://topic.csdn.net/u/20120911/22/61a34a6d-13da-4f0a-b05c-02c996fa39a0.html

同样的题
龙四 2012-10-11
  • 打赏
  • 举报
回复
可能会死循环,打印出0或者42
也可能啥都没打印
……

http://www.ticmy.com/?p=5

http://www.ticmy.com/?p=118
gengliangyu 2012-10-11
  • 打赏
  • 举报
回复
如果不加 volatile,可能打出 0 或者 42
如果加volatile, 只能打出42

因为volatile 关键字有一个作用是 禁止指令重排序优化,就是java 内存模型中所描述的 Within Thread As If Serial Semantics
大数据新鸟 2012-10-11
  • 打赏
  • 举报
回复
附带的测试程序: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


大数据新鸟 2012-10-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中关于类的初始化和类的加载放面的知识
xiejin90314 2012-10-11
  • 打赏
  • 举报
回复
看了楼主的结贴率。。。。。。
oO临时工Oo 2012-10-11
  • 打赏
  • 举报
回复
学习了 Volatile

http://qingfeng825.iteye.com/blog/152269

最终看这篇文章看懂了原理
wangzi9521 2012-10-11
  • 打赏
  • 举报
回复
42是正解,因为不管线程yield让出多少次,总归是要让出去的。然后执行number = 42,之后打印出来。
jediael_lu 2012-10-11
  • 打赏
  • 举报
回复
又是这种
龙四 2012-10-11
  • 打赏
  • 举报
回复
java定义了一种内存模型,也就是Java Memory Model,所有jvm最低要实现该模型,但可以比这个模型更高。什么概念?也就是说在jvm1实现上运行没问题(就像这里的这个程序一样,未充分同步(包括volatile和synchronized)),可能是因为凑巧,可能是因为jvm1实现的时候高于JMM;如果将此程序放到仅实现了JMM的最低要求,那么程序就有问题了。为什么要定义JMM,一为并发效率(每次都访问内存是非常低效的,CPU的缓存,寄存器更高效);二为跨平台(每个平台内存与CPU的缓存,寄存器之间的同步时机)

JMM就是规定了多线程下什么时候需要重新将内存中的数据读取到工作缓存,什么时候要将工作缓存中的数据写回内存

[Quote=引用 8 楼 的回复:]

你试了并不表示它一直就那样运行

都是因为可见性和指令重排序问题,main线程修改number和ready(都是非volatile的且未同步),那么ReadThread究竟能不能看到这种修改呢?jvm是没有保证的,可能出现一下情形:
1、ReadThread看到了number为42,ready为false
2、ReadThread看到了number为0,ready为false
3、Re……
[/Quote]
龙四 2012-10-11
  • 打赏
  • 举报
回复
你试了并不表示它一直就那样运行

都是因为可见性和指令重排序问题,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线程的赋值还没做


[Quote=引用 6 楼 的回复:]

引用 2 楼 的回复:

可能会死循环,打印出0或者42
也可能啥都没打印
……

http://www.ticmy.com/?p=5

http://www.ticmy.com/?p=118

为什么是0或者死循环啊。。。我试了个循环都是42啊。。。。。
[/Quote]

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧