volatile如何保证可见性

volatile如何保证可见性?

我们都知道volatile具有可见性和有序性,但是不保证原子性。
这篇文章主要是看一下volatile如何保障可见性的。

我们知道一般我们在使用多线程的过程中,为了保持同一个变量的一致性,都会使用volatile关键字进行修饰。
那么volatile是在内存模型中起到一个什么样的作用,是怎么样保持多个线程中同一个变量的一致性呢。

我写了一个简单的例子,如果第2个线程修改了initFlag的值,我希望线程1能立刻感知到值得变化跳出死循环。这里没用volatile修饰,线程2修改了initFlag的值后,线程1还是在死循环,并没有立刻感知到initFlag值得变化,并不是我想要得结果。
在这里插入图片描述
在这里插入图片描述
那么我们来了解一下原理,这了解原理之前,我们要画一个内存模型,那样更好帮助我们理解。
首先我们要知道JMM(java内存模型)得原子操作,有8种。

如下:分别对应图中得顺序

read(读取):从主内存读取数据
load(载入):将主内存的数据写入工作内存
use(使用):从工作内存读取数据计算
assign(赋值):将计算好的值重新赋值到工作内存中
store(存储):将工作内存的值写入主内存
write(写入):将store过去的变量值赋值给主内存中的变量
lock(锁定):将主内存变量枷锁,标识未线程独占状态
unlock(解锁):将主内存变量解锁,解锁后其他线程可以锁定该变量
在这里插入图片描述
我们要特别注意一下总线这个东西。cpu和主内存是两个独立得硬件,不能直接交互数据,是通过总线来交互数据得。主内存与cpu之间进行数据交互都会经过总线。

volatile关键字会开启总线得mesi缓存一致性协议。

mesi缓存一致性协议:多个CPU从主内存读取同一个数据到各自得高速缓存,当其中某个cpu修改了缓存里得数据,该数据会马上同步回主内存,其他cpu通过总线嗅探机制可以感知到数据得变化从而将自己缓存里得数据失效

在这里插入图片描述
1.线程2修改值,以后会经过总线,然后写回主内存。
2.volatile开启总线mesi缓存一致性协议,每个cpu 都会监听总线
3.当知道其他cpu修改了变量值,立刻会失效自己工作内存中得值。
4.重新去主内存取值。

但是第四步,重新去主内存取值,怎么保障读取是最新得值呢。

把Java代码反编译后,发现会在initFlag = true;这行代码之前加 LOCK
在这里插入图片描述

volatile缓存可见性实现原理底层实现主要是通过汇编LOCK前缀指令,它会锁定这块内存区域得缓存(缓存行锁定)并回写到主内存。
IA-32架构软件开发手册对lock指令得解释:
1.CPU会将当前处理器缓存行的数据立即写回到系统内存
2.这个写回内存得操作会引起在其他CPU里缓存了该内存地址得数据无效(MESI协议)

如下图:
在这里插入图片描述
线程2修改值了以后,会在store之前加锁,锁住主内存得值,这期间其他线程的等锁释放后才能访问,主内存得值修改后会释放锁,这样保障了其他线程读取到得是最新得值。这里锁得颗粒度很小,所以影响忽略不计。这就是Volatile保障可见性得基本原理。

转载自:https://blog.csdn.net/weixin_38818613/article/details/119804684

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值