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

Java Volatile关键字分析(二)

在上文介绍了Volatile在编程语言层面支持并发编程的内存可见性,cpu侧是如何实现的。

下面是没有使用Volatile的代码示例

如上代码所示定义的counter共享计数器对象,并没有使用volatile ,synchronize这样的关键,在对共享对象进行多线程读写的情况下,是无法保证一致性性和准确性的。因为在读写操作时,先是对本地缓存进行操作的。如下图所示:

如上图所示,cpu cache数据与主内存数据是不一致的,Thread2线程没有看到一个变量的最新值,因为它还没有被另一个线程写回主内存,这个问题被称为“可见性”问题。一个线程的更新对其他线程不可见。但,上面代码中的counter++,这是个复合操作,只能保证可见性,却不能保证原子性。

Volatile变量自身特性:

1. 可见性:对一个Volatile变量的读,总是能看到任意线程对这个Volatile变量最后的写入。如线程1写counter变量,线程2读取时,对于线程1操作该变量的前后都是可见的。

2. 原子性:对任意单个变量的读写具有原子性,但像counter++这种复合操作不具有原子性。

看到这里有没有注意到上面的代码有问题,也就是这个counter++ 操作,这个复合操作有读取、计算、写入,无法保证原子性,所以在主内存中的数据会出现覆盖的情况,数据不准确,根据实际情况选择使用。

完整的volatile可见性保证小技巧

示例代码如下:

可见性保证遵循以下规则:

如果线程A写入一个volatile变量,线程B随后读取了同样的volatile变量,则线程A在写入volatile变量之前的所有可见的变量值,在线程B读取volatile变量后也同样是可见的。

如果线程A读取一个volatile变量,那么线程A中所有可见的变量也会同样从主存重新读取。

完整的volatile可见性保证意味着,在写入varC变量时,线程中所有可见变量也会写入主内存,在读取varC变量时,varA、varB也会从主内存读取。

可以将对volatile变量的读写理解为一个触发刷新的操作,因此,应当尽量将volatile的写入操作放在最后,而将volatile的读取放在最前,这样就能连带将其他变量也进行刷新。

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

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券