谈谈Volatile

前言

Volatile的能够保证并发编程的两大特性

一是可以保证可见性,即一个线程对共享变量的修改,能够对其他线程立即可见

二是可以保证有序性,即防止操作系统通过指令重排序来优化程序,毕竟在高并发的场景下,要保证重排序后的执行结果跟排序前的一致,是非常难的

正文

本文将围绕Volatile的三个内来展开

  1. 内存模型(JMM)
  2. 内存语义
  3. 内存屏障
1. 内存模型(JMM)

关于L1、L2、L3高速缓存,L1和L2是一个CPU一个,L3是整个计算机共享一个,所以下图可能画的不太准确(懒得重画了),不过不影响各位看官食用哈
在这里插入图片描述

  1. 由于路途遥远,所以各国需要通过使者L1、使团L2(可能还会有L3),来跟王国公主联系
  2. 王国CPU1和王国CPU2各自为政,互不往来,使者只会跟使团联系,不会彼此联系,信息严重滞后
  3. 如果CPU1的王子迎娶了公主A,过几个月后,又传来CPU2的王子迎娶公主B的消息,那么公主可能会被判重婚罪

看不懂的小伙伴,建议先去百度一下Java内存模型,这里只是以一个不太恰当的比喻来形容一下,毕竟学习嘛,总得自娱自乐一下,要不然可太苦了
在这里插入图片描述

由于内存寸土寸金,禁不起这么折腾,所以有了各王国间签订了一个MESI协议,这样各国的王子就能实时知道公主的婚姻情况了

MESI协议,又称缓存一致性协议,用于管理多个 CPU cache 之间数据的一致性。

在这里插入图片描述

关于MESI协议,大佬的这篇从CPU缓存看缓存的套路,已经讲得非常清楚了,建议多看几遍

2. 内存语义

在这里插入图片描述
这个嘛,也就是字面上的意思了,简单的理解呢,就是遇到volatile,读写都会走主内存,缓存暂时就失效了
在这里插入图片描述
经过编译器,到了汇编层面,我们可以看到,volatile修饰的变量,会加上一个Lock前缀指令,而这个Lock前缀指令会锁缓存(替代锁总线)。关于总线锁和缓存锁,这里就不展开了,感兴趣的小伙伴自行百度哈~(等我以后有空了再补充吧)

3. 内存屏障

Volatile使用硬件层的内存屏障(分为两种Load Barrier 和 Store Barrier即读屏障和写屏障),来阻止屏障两侧的指令重排序

在这里插入图片描述

下面这段关于读写屏障的描述,来自知乎用户@随风而逝对关于内存屏障的几个问题?的回答,会比其他答案好理解点

读写屏障包括全能型屏障都属于指令。读屏障作用于Invalidate queue,每次cpu遇到这个指令都将自己积压已久的invalidate ack处理掉,具体就是使得对应的缓存失效,这样自己再读的时候,能保证读到最新的副本。写屏障作用于store buffer,将处于store buffer中的写操作真正执行掉,具体就是向其他CPU发送invalidate cache 的消息,写自己的独占缓存。全能型屏障这两件事都做。

谈到指令重排序,就不得不提happens-before规则,happens-before规则定义一些禁止编译优化的场景
在这里插入图片描述
静下心来耐心看,光看文字,相信大家还是能够看懂的,就是面试吹水的时候,记不太住,毕竟这是定好的规则

小小总结一下

在这里插入图片描述

大佬们的劳动成果(排名不分先后)

MESI协议
从CPU缓存看缓存的套路
面试官最爱的volatile关键字
带你了解缓存一致性协议 MESI

结语

Volatile对于并发编程来说,总归是绕不开的,平时也看了很多零散的知识,今天也算是稍微整理了一下,相信对以后的复习和面试能够有所帮助。

最后还是那句,本人所有博客不做商业用途,如若涉及侵权,还请联系删除,互相学习,一起进步

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值