首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Java并发编程 volatile引用类型的可见性问题

介绍

在之前的文章《

Java并发编程~变量可见性和volatile

》中,我们提到在多线程场景下,volatile可以保证变量的可见性。之前的变量是值类型,如果变量是对象引用类型,这种可见性还能保证吗?实际上,对象引用本身的可见性还是保证的,但是对于对象中的字段值,可见性是不能保证的。

我们看如下案例。

对象引用的可见性问题

在上面的代码中,我们定义了一个值对象 ,内部包含两个字段 和 。我们在主程序中定义一个 ,即引用 本身是volatile的。

我们启动两个线程,写线程创建新的 对象 ,程序逻辑是保证 和 相等;读线程则读取 中的 和 的值,读取后进行比对,如果 和 不相等,则输出不相等的情况。

我们预期读线程读到的 和 值始终相等,但是如果我们将程序循环运行足够多次,比如2万次,偶尔我们会得到 和 不相等的情况,也就说虽然 引用本身是volatile的,但是vo内部的字段值可能会出现对其它线程的可见性和不一致情况。

样例输出:

注意这个输出不确定,取决于计算机配置,你可能需要多跑几次才能遇到不一致情况。

如何解决上述问题,有两种方法,下面给出案例代码。

方法一:拷贝字段值

上述代码运行再多次也不会出现不一致情况,区别在于 方法拷贝了字段的值,可以避免不一致问题。

方法二:使用原子引用类型AtomicReference

上述代码运行再多次也不会出现不一致情况, 可以保证原子引用对象中的字段值对读线程始终可见,避免一致性问题。

结论

对于引用类型使用volatile,可以保证引用类型变量本身的可见性,但是其内部的字段值还是可能存在可见性问题。

解决上述问题的一种办法是拷贝值,另外一种办法是使用原子引用类型AtomicReference。

本文代码已经上传github,下载请参考附录。

附录

参考代码:https://github.com/spring2go/tutorials/tree/master/core-java-concurrency

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180612G1P26S00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券