Volatile

本文详细探讨了volatile关键字的作用,包括禁止指令重排和保证可见性。在JVM层面,volatile通过指令屏障实现。在汇编层面,volatile使用lock指令配合MESI缓存一致性协议来确保多处理器环境下的数据一致性。 MESI协议确保当一个处理器修改了共享内存时,其他处理器能立即感知并更新其缓存。
摘要由CSDN通过智能技术生成

Volatile

volatile 作用

  1. 禁止指令重排
  2. 可见性

JVM层面实现

jvm实现volatile是使用指令屏障实现的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ochndVkF-1602603909946)(C:\Users\sunwzh\Downloads\Volatile内存屏障.png)]

汇编层面实现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-opiQdYpm-1602603909947)(图片/Volatile/image-20201009233018270.png)]

汇编使用lock指令实现+MESI缓存一致性协议实现的

Lock指令相当于一条内存屏障,指令重排时,不能把后面的指令重排到内存屏障之前的位置.

以前的CPU lock都是用于锁定总线实现的,但是这样效率太低了

现在的CPU 使用锁缓存来代替锁总线

多处理器、多线程环境下,若某个线程对声明了volatile的变量进行写操作,JVM会向处理器发送一条LOCK前缀的指令,将这个变量所在缓存行的数据写回主内存,LOCK前缀指令通过 “锁缓存” 可以确保回写主内存的操作是原子性的。

但是,其它处理器的缓存中存储的仍然是 “旧值” ,并不能保证可见性,因此,还要借助缓存一致性协议:每个处理器通过嗅探在总线上传播的数据来检查自己的缓存值是否过期,当处理器发现自己缓存行对应的内存地址被修改时,就会设置当前缓存行为无效,需要对数据进行修改的时候会重新从主内存中加载。如此,便保证了可见性。

缓存一致性协议

所有内存的传输都发生在一条共享的总线上,而所有的处理器都能看到这条总线:缓存本身是独立的,但是内存是共享资源,所有的内存访问都要经过仲裁(同一个指令周期中,只有一个CPU缓存可以读写内存)。

CPU缓存不仅仅在做内存传输的时候才与总线打交道,而是不停在嗅探总线上发生的数据交换,跟踪其他缓存在做什么。所以当一个缓存代表它所属的处理器去读写内存时,其它处理器都会得到通知,它们以此来使自己的缓存保持同步。只要某个处理器一写内存,其它处理器马上知道这块内存在它们的缓存段中已失效。

MESI 是最主流的缓存一致性协议,在MESI协议中,每个缓存都有一个标志位来标记缓存行的状态,可以用2bit来实现.它们分别是

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RT0PEuwa-1602603909948)(C:\Users\sunwzh\AppData\Roaming\Typora\typora-user-images\image-20201009232305913.png)]

每个核心都维护自己的Cache的状态。如果对于同一份内存数据在多个核里都有cache,则状态都为S(shared)。一旦有一核心改了这个数据(状态变成了M),其他核心就能瞬间通过ringbus(环形总线)感知到这个修改,从而把自己的cache状态变成I(Invalid),并且从标记为M的cache中读过来。同时,这个数据会被原子的写回到主存。最终,cache的状态又会变为S。

https://www.pianshen.com/article/81043901/

https://www.zhihu.com/question/65372648

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值