为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕虎7371278 2019-05-23 16:24:37
《Java并发编程实战》3.1节的一段代码:publicclassNoVisibility{privatestaticbooleanready;privatestaticintnumber;privatestaticclassReaderThreadextendsThread{publicvoidrun(){while(!ready)Thread.yield();System.out.println(number);}}publicstaticvoidmain(String[]args){newReaderThread().start();number=42;ready=true;}}按照书中所讲,这段代码不一定输出42,有可能陷入死循环。原因是代码中没有足够的同步机制,无法保证主线程写入的ready他number对读线程是可见的。也有可能是0,原因是“重排序”,读线程看到了主线程写入的ready却没有看到number。但是经过多次测试,始终输出42,既没有输出0,也没有死循环。为了验证书中所说的主线程修改对读线程不可见,我改写了代码:publicclassNoVisibilityLoop{privatestaticintnumber;privatestaticclassReaderThreadextendsThread{publicvoidrun(){while(true){System.out.println(number);try{Thread.sleep(200);}catch(InterruptedExceptione){}}}}publicstaticvoidmain(String[]args)throwsInterruptedException{newReaderThread().start();Thread.sleep(1000);number=42;}}多次测试输出结果是:0000042424242这个结果说明了主线程写入的number对读线程是可见的。但是这本书的作者一堆大牛,不会搞错的。还请大家帮忙看看我的验证方法哪里出问题了,谢谢。运行环境:jdk1.8.0_101,server模式。
查看完整描述

2 回答

?
HUX布斯

TA贡献1876条经验 获得超6个赞

首先测试多次正确也不能保证完全就是正确的,其次这本书是jdk5和6了,jdk8估计做了些优化,
privatestaticbooleanready;
privatestaticintnumber;
privatestaticclassReaderThreadextendsThread{
@Override
publicvoidrun(){
inti=0;
while(!ready){
i++;
//Thread.yield();
}
System.out.println(number);
}
}
publicstaticvoidmain(String[]args)throwsException{
newReaderThread().start();
TimeUnit.MILLISECONDS.sleep(9);
number=42;
ready=true;
}
把thread.yield换成i++或者sleep与否结果都有差别这种执行顺序是指令重排决定的,不用volatile没法保证
                            
查看完整回答
1 反对 回复 2019-05-23
?
杨__羊羊

TA贡献1943条经验 获得超7个赞

原文的意思是让你重复多次运行这段代码大概运行几十次甚至上百次,可能出现一次死循环,而这个在实际开发中是不可取的
而这是代码设计缺陷的问题,所以建议不要这么编程,要保持主副线程的同步性不要用这样的写法,你继续往后看,这书既然这么说,可能会有别的解决方案来帮你理解他描述的原理
                            
查看完整回答
反对 回复 2019-05-23
  • 2 回答
  • 0 关注
  • 505 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信