论坛首页 Java企业应用论坛

Java Concurrency in Practice(Java并发编程实战)这本书过时了吗

浏览 12578 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2013-07-10   最后修改:2013-07-10
donlianli 写道
ticmy 写道

可见性问题,只是说,非充分同步的情况下,允许出现,但并一定就得出现,如这个例子:

http://ifeve.com/concurrency-visibility/

 

又如这篇中http://ifeve.com/syn-jmm-visibility/提到的

在缺乏同步的情况下,模型还允许不一致的可见性。比如,得到一个对象的一个字段的最新值,同时得到这个对象的其他字段的过期的值。同样,可能读到一个引用变量的最新值,但读取到这个引用变量引用的对象的字段的过期值。
不管怎样,线程之间的可见性并不总是失效(指线程即使没有使用同步,仍然有可能读取到字段的最新值),内存模型仅仅是允许这种失效发生而已。因此,即使多个线程之间没有使用同步,也不保证一定会发生内存可见性问题(指线程读取到过期的值),java内存模型仅仅是允许内存可见性问题发生而已。在很多当前的JVM实现和java执行平台中,甚至是在那些使用多处理器的JVM和平台中,也很少出现内存可见性问题。共享同一个CPU的多个线程使用公共的缓存,缺少强大的编译器优化,以及存在强缓存一致性的硬件,这些都会使线程更新后的值能够立即在多线程之间传递。这使得测试基于内存可见性的错误是不切实际的,因为这样的错误极难发生。或者这种错误仅仅在某个你没有使用过的平台上发生,或仅在未来的某个平台上发生。这些类似的解释对于多线程之间的内存可见性问题来说非常普遍。没有同步的并发程序会出现很多问题,包括内存一致性问题。

 

又如这个例子中的:http://ifeve.com/doublecheckedlocking/#firstreason

也只是Symantec JIT的系统上重现了场景,其它平台未必能。

书上明确说明,第一段代码将无法停止,第二段代码可能会出现1,1的情况。但实际上并非书上所说。

 

 While it may seem obvious that NoVisibility  will print 42 , it is in fact possible that it will print zero, or never terminate at all!  

 

 

 NoVisibility could loop forever because the value of ready might never become visible to the reader thread. Even more strangely, NoVisibility could print zero because the write to ready might be made visible to the reader thread before the write to number, a phenomenon known as reordering.

 

原文的语气没那么强。同时也未指明在哪家的JVM以及什么版本上会出现。实际上,这完全是利用JVM应该提供的最小保障所做的理论分析。各厂家在实现JVM时可以提供更强的保障。

0 请登录后投票
   发表时间:2013-07-11  
Thread.yield(); 记得原来 在书上这么解释的,该方法只是当前线程自动放弃运行态,但是这只是一种建议,不一定会实现。也就是说,这个Thread.yield()方法,类似于修改了多线程的优先级,但实际上未必会发生。而且很少看到有用到Thread.yield();的代码了。
个人看法!
0 请登录后投票
   发表时间:2013-07-11  
yield() 这方法就应该从jdk里面去掉 .
0 请登录后投票
   发表时间:2013-07-11  
可见性问题本来就是不一定发生了,我上周还帮别人看过一个怪事。
在 while(!ready)这种方法里面,如果什么都不干,永远没法停止,加了一个log.info,居然可见了。。
0 请登录后投票
   发表时间:2013-07-16  
yield()为啥要去掉。。。yield()只是线程放弃cpu时间让其他线程执行,非常有用的函数
为什么要去掉?调用这个函数后会上下文切换,线程回把变量会写到主内存里面,下次执行的时候会重新读取主内存里面的。所以屏蔽掉yield()就可以避免了内存的同步。。。system.out.print函数也是,这个函数里面可能加锁了,所以也回同步内存。。。所以去掉这些函数才有效果。。。。
0 请登录后投票
   发表时间:2013-07-16  
log.info一样回同步,。。只要你在线程里面调用了可能同步的函数,都会同步内存。。。
0 请登录后投票
   发表时间:2013-07-16  
yield()会切换cpu上下文。。。。寄存器的东西肯定全部失效,下次调用的时候重新同步了。。。主内存!!!!
0 请登录后投票
   发表时间:2013-07-16  
zuoge85 写道
log.info一样回同步,。。只要你在线程里面调用了可能同步的函数,都会同步内存。。。

你是说在一个if块里面,如果有synchronized块,虚拟机会让if statement里面涉及的对象也同步内存?
0 请登录后投票
   发表时间:2013-07-16  
反正寄存器里面的肯定回同步,因为当前线程要从cpu里面切换出来
0 请登录后投票
   发表时间:2013-07-16  
下次执行的时候重新读取到寄存器
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics