java并发编程第八章ValueLatch在读取的时候是否有必要使用内置锁synchronized?关于final重排序的问题

时间:2018-01-18 17:10:02   浏览:次   点击:次   作者:   来源:   立即下载

这里ValueLatch是①个线程安全的类,但是据我个人理解在getValue函数中没有必要使用synchronized(this)同步读取value。

因为以下④个语句

value = newValue; //①

done.countDown(); //②

done.await(); //③

return value; //④

根据happens-before中的程序顺序规则,①和②之前执行,③在④之前执行。

根据CountDownLatch的happens-before原则,②在③之前执行。

根据传递性规则,①在④之前执行。所以已经保证了读操作的可见性,在getValue方法内就没有必要再用内置锁synchronized了。望各位大侠指正下,我的想法是否正确?

谢@ 莱恩臣 邀

总之Synchronized可以保证可见性和原子性(Synchronization and the Java Memory Model)可见性①节 在Java内存模型中,synchronized规定,线程在加锁时,先清空工作内存→在主内存中拷贝最新变量的副本到工作内存→执行完代码→将更改后的共享变量的值刷新到主内存中→释放互斥锁

分析题主回答和题目的区别题目:

①.read操作会从排序?await和Sync入口重拍序吗?根据JSR-①③③资料The JSR-①③③ CookbookThe JSR-①③③ Cookbook。可以看到(① · ③)这个坐标,是没有内存屏障的,可以重排序,所以await()这个调用时可以和sync(this)重拍的,然后看(③ · ①)是有屏障的所以sync方法块里面的不可以排序到sync方法块前面去。总的来说就是sync方法前面的代码是可以重排序的,但是①定会happens-before方法块里面的代码。

通过下面这个表格对比可以分清楚是如何加屏障的

LoadLoad屏障:对于这样的语句Load①; LoadLoad; Load② · 在Load②及后续读取操作要读取的数据被访问前,保证Load①要读取的数据被读取完毕。StoreStore屏障:对于这样的语句Store①; StoreStore; Store② · 在Store②及后续写入操作执行前,保证Store①的写入操作对其它处理器可见。LoadStore屏障:对于这样的语句Load①; LoadStore; Store② · 在Store②及后续写入操作被刷出前,保证Load①要读取的数据被读取完毕。StoreLoad屏障:对于这样的语句Store①; StoreLoad; Load② · 在Load②及后续所有读取操作执行前,保证Store①的写入对所有处理器可见。它的开销是④种屏障中最大的。在大多数处理器的实现中,这个屏障是个万能屏障,兼

那么总的来说对于题目而言,③ hapepens-before ④ · ①和② 也happends-before ④ 所以最后读取value是肯定线程安全的。同时根据sync有可见性,可以及时保障value是正确的值

②.针对第②种情况,(hp=happens-before)

明显的作为就是利用volatile的可见性和内存语义来保证的线程安全。volatile写之前会有storestore的内存屏障, JMM会把该线程对应的本地内存中的共享变量刷新到主内存 所以value也是线程安全的。和第①种有区别,但是都差不多。有些会说这种方式效率更高,其实也不①定sync现在已经非常优化了

\", \"extras\": \"\", \"created_time\": ①④⑨⓪⑨⑦②④①③ · \"type\": \"answer

收起

相关推荐

相关应用

平均评分 0人
  • 5星
  • 4星
  • 3星
  • 2星
  • 1星
用户评分:
发表评论

评论

  • 暂无评论信息