为什么有MESI了还要volatile?你真的了解volatile吗

12 篇文章 0 订阅
6 篇文章 2 订阅

1. 前言

不知道从什么时候开始,百度volatile相关的文章基本上都是一个套路:

先从CPU缓存架构、计算机的内存模型、MESI、volatile实时触发数据一致性……

或许是从某个培训机构讲师嘴里说出来的,也可能是某位P9大佬呕心沥血花了几个月整理出来最后被共同封杀的笔记里记载的。

一开始我也对这套理论坚信不疑,但最近看了一段相关的资料,发现这套理论一些细节并不能站稳脚跟,或者说讲得不够透彻。(PS:默默把自己之前发布的几篇相关文章删了)

首先强调一点,volatile和MESI这两个东西没有必然关系。MESI是缓存一致性的一种实现手段,而volatile是在java层面只是jvm这款软件的一段代码增强,意图是保证变量的可见性和有序性


2. volatile的作用与原理

volatile在java层面只是JVM这款软件的一段代码增强,意图是保证变量的可见性和有序性。

首先从可见性来说,虽然有缓存一致性协议可以保证各个CPU从缓存到主存之间的一致性。但问题是,数据得先到高速缓存才行啊,它可能还在写缓冲区storeBuffer。而且,对于有的CPU架构,还有无效化队列invalidQueue

而volatile的目的就是告诉cpu,这个变量不需要缓冲区中而是每次都强制刷到缓存。只要刷到缓存,因为MESI或者其它缓存一致性协议的实现,各CPU缓存一致,所以即可实现可见性

而有序性则是做了两件事情:

  1. 禁止编译器进行指令重排序
  2. 使用内存屏障来避免storeBuffer和invaildQueue造成的指令乱序


3. 为什么有了MESI还需要volatile关键字

其实理解了上面你就可以不用读这个了。

明确一个点,缓存一致性协议是为了保证多个cache与内存之间的数据同步,但是volatile的语义是为了从软件层面来保证可见性和有序性。

它并不关注底层是通过什么技术来实现的,因此单靠MESI并不能满足volatile,它只是volatile语义实现的一部分

MESI也是默认生效的,要不然你以为操作系统线程间的数据可见性是怎么保证的,别再说什么volatile触发了MESI……


4. 内存屏障是什么?它是怎么保证有序性的?

内存屏障是干嘛的?防止指令重排序嘛,为什么会有指令重排序?指令重排是什么?怎么防止的?

其实CPU真没有智能到能自己重排硬件指令,所有重排几乎都是storeBuffer和invaildQueue造成的,大部分CPU只是按照简单流水线方式去执行硬件指令

不过编译器的指令重排确实是由volatile禁止了。

4.1 Store Buffer & Invalid Queue

MESI机制不止四个状态那么简单,除了四个状态之外,还有一套消息机制,正是因为这套消息机制带来了性能的下降, 于是也就有了 storeBuffer, invalidQueue等优化措施。

但是这些优化措施又带来了另外的问题, 一些立马需要被其他CPU核心感知的修改, 因为storeBuffer的优化迟迟无法写入cache,MESI机制无法生效, 其他CPU核心就感知不到。

所以CPU就提供了读、写屏障指令,让程序员或编译器明确声明,这里的修改需要立即写入cache, 不能在storeBuffer里存着,效果就是修改完变量后, 需要立即刷storeBuffer里的数据到cache,不能等CPU空闲时再刷。

InvalidQueue差不多亦是如此。

读、写屏障指令的本质就是把默认的异步刷buffer, 强制切换成同步刷buffer。

5. synchronized是怎么保证可见性的?

JMM中关于synchronized有如下规定,线程加锁时,必须清空工作内存中共享变量的值,从而使用共享变量时需要从主内存重新读取;线程在解锁时,需要把工作内存中最新的共享变量的值写入到主存,以此来保证共享变量的可见性。

有序性?拜托,代码块都只允许一个线程访问了,它乱不乱序有什么影响吗?

6. 相关资料

这里留一些相关资料,本文大部分也是参考其中。
我并没有去验证过这些理论的真实性,但至少这套理论是能够逻辑自洽的,并且深度超越了目前网络上大部分博文,看完之后希望大家能够提出自己的见解。

  1. JMM到底如何理解?JMM与MESI到底有没有关系?
  2. 既然CPU有缓存一致性协议(MESI),为什么JMM还需要volatile关键字?
  3. 当我们在谈论cpu指令乱序的时候,究竟在谈论什么?
  4. 缓存一致性协议的工作方式
  5. 内存屏障的来历
  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值