“了解高并发底层原理”,面试官:讲一下MESI(缓存一致性协议)吧
目录
- 前言:
- 1.什么是(Who):
- 2.为何来(How):
- 2.1缓存不一致带来的后果
- 2.2解决方法:
- 3.是什么(What)
- 3.1数据在缓存中的四种状态:
- 3.2MESI的六种消息(请求消息和响应消息)
- 3.3MESI四种状态通过六种消息进行转换(利用3.1与3.2章节的知识点)
前言:
- JVM不是真实存在的,只是一个抽象的概念。volatile关键字底层也是借助MESI缓存一致性协议和内存屏障得以实现有序性和可见性的。
- MESI是计算机底层的协议,所有支持高并发的编程语言的底层都是基于MESI协议来保证并发安全的,所以MESI协议更有助于我们去理解底层原理,知其所以然!
- 本期围绕着,什么是(Who),为何来(How),是什么(What),这三点内容来进行讲解该协议。
1.什么是(Who):
MESI(Modified Exclusive Shared Or Invalid)协议是基于Invalidate的高速缓存一致性协议,并且是支持回写高速缓存的最常用协议之一。 它也被称为伊利诺伊州协议(由于其在伊利诺伊大学厄巴纳 - 香槟分校的发展)。用于解决缓存一致的问题。
2.为何来(How):
2.1缓存不一致带来的后果
如上图,数据加载的流程如下:(从内存到寄存器)
将程序和数据从硬盘加载到内存中
将程序和数据从内存加载到缓存中(目前多三级缓存,数据加载顺序:L3->L2->L1)
CPU将缓存中的数据加载到寄存器中,并进行运算
CPU会将数据刷新回缓存,并在一定的时间周期之后刷新回内存
现在的CPU基本都是多核CPU,服务器更是提供了多CPU的支持,而每个核心也都有自己独立的缓存,当多个核心同时操作多个线程对同一个数据进行更新时,如果核心2在核心1还未将更新的数据刷回内存之前读取了数据,并进行操作,就会造成程序的执行结果造成随机性的影响,举个例子如下:
如果由两个cpu同事开始读取了int i =0,然后同同时执行如下语句,会出现如下情况:
......
int i = 0;
i++;
......
刚开始,i初始化为0,假设有两个线程A,B,
- A线程在CPU0上进行执行,从主存加载i变量的数值到缓存,然后从缓存中加载到寄存器中,在寄存器中执行i+1操作,得到i的值为1,此时得到i等于1的值还存放在CPU0的缓存中;
- 由于线程A计算i等于1的值还存放在缓存中,还没有刷新会内存,此时线程B执行在CPU1上,从内存中加载i的值,此时i的值还是0,然后进行i+1操作,得到i的值为1,存到CPU1的缓存中,
- A,B线程得到的值都是1,在一定的时间周期之后刷新回内存
4.写回内存后,两次i++操作之后,其值还是1;
可以看到虽然我们做了两次++i操作,但是只进行了一次加1操作,这就是缓存不一致带来的后果。
2.2解决方法:
在先前的解决方案中,大致有两种思路:
总线加锁的方式:
- 先前大佬们提供了一种总线加锁的方式,而总线加锁是对整个内存进行加锁,在一个核心对一个数据进行修改的过程中,其他的核心也无法修改内存中的其他数据,这样对导致CPU处理性能严重下降。
总线加锁的方式导致CPU性能严重下降,此时我们提出了缓存一致性协议(MESI):
- 缓存一致性协议提供了一种高效的内存数据管理方案,它只会对单个缓存行(缓存行是缓存中数据存储的基本单元)的数据进行加锁,不会影响到内存中其他数据的读写。
- cache line,缓存行是为了简化与RAM之间的通信,高速缓存控制器是针对数据块,而不是字节进行操作的。从程序设计的角度讲,高速缓存其实就是一组称之为缓存行(cache line)的固定大小的数据块。
因此,我们引入了缓存一致性协(MESI)议来对内存数据的读写进行管理。
3.是什么(What)
3.1数据在缓存中的四种状态:
MESI的英文全程为:Modified Exclusive Shared Or Invalid,有四种状态,分别对应其英文单词,如下:
状态 | 具体描述 | 状态所在缓存对应的CPU是否独占数据 | cache line 是否是最新数据 | 对数据的写入 |
---|---|---|---|---|
M: 被修改(Modified) | 该缓存行只被缓存在该CPU的缓存中,并且是被修改过的(dirty),即与主存中的数据不一致,该缓存行中的数据需要在未来的某个时间点(允许其它CPU读取主存中相应数据之前)写回(write back)主存。当被写回主存之后,该缓存行的状态会变成独享(exclusive)状态。 | 是 | 是 | 可以 |
E: 独享的(Exclusive) | 该数据只被缓存在该CPU的缓存行中,它是未被修改过的(clean),与主存中数据一致。该状态可以在任何时刻当有其它CPU读取该内存时变成共享状态(shared)。同样地,当CPU修改该缓存行中内容时,该状态可以变成Modified状态。 | 是 | 是 | 可以 |
S: 共享的(Shared) | 该状态意味着该数据可能被多个CPU缓存读取,并且各个缓存中的数据与主存数据一致(clean),当有一个CPU修改自己的缓存行中的数据时,数据对应的缓存行状态变成Modified状态,其它CPU中该缓存行变成无效状态(Invalid)。 | 否 | 是 | 可以 |
I: 无效的(Invalid) | 该缓存是无效的(可能有其它CPU修改了该缓存行)。 | 否 (无数据) | 无数据 | 无数据,不可以 |
3.2MESI的六种消息(请求消息和响应消息)
cpu接收响应消息的顺序决定了其他cpu感知到的当前线程的执行顺序
- read:(请求消息)
“read” 消息用来获取指定物理地址上的 cache line(如果在缓存中,从缓存中取,不在缓存中则从内存中取) 数据。 - read response:(响应消息)
"read response"消息包含先前“read”消息请求的数据。此“read response”消息可能来自内存或其他CPU的缓存。 - invalidate:(请求消息)
Invalidate。该消息将其他 CPU cache 中指定的数据设置为失效。该消息携带物理地址,其他 CPU cache 在收到该消息后,必须进行匹配,发现在自己的 cache line 中有该地址的数据,那么就将其从 cahe line 中移除,并响应 Invalidate Acknowledge 回应。 - invalidate acknowledge:(响应消息)
该消息用做回应 Invalidate 消息。 - read invalidate:(请求消息)
该消息中带有物理地址,用来说明想要读取哪一个 cache line 中的数据,同时指示其他缓存删除数据。可以看作是 read + Invalidate 消息的组合,“read invalidate”消息需要“read response”和一组“invalidate acknowledge”消息作为应答。 - writeback:
“writeback”消息包含要写回内存的地址和数据(也可能是沿途“窥探”到其他cpu的缓存中)。该消息用在 modified 状态的 cache line 被置换时发出,用来将最新的数据写回 memory 或其他下一级 cache 中。
3.3MESI四种状态通过六种消息进行转换(利用3.1与3.2章节的知识点)
上图的转换详细说明:
- a
cache 通过 writeback 将数据回写到 memory 或者下一级 cache 中。这时候状态由 modified 变成了 exclusive 。 - b
cpu 直接将数据写入 cache line ,导致状态变为了 modified 。 - c
CPU 收到一个 read invalidate 消息,该消息中带有物理地址,用来说明想要读取哪一个 cache line 中的数据,同时指示其他缓存删除数据。此时 CPU 必须将对应 cache line 设置成 invalid 状态 , 并且响应一个 read response 消息和 invalidate acknowledge 消息。 - d
CPU 需要执行一个原子的 readmodify-write 操作,并且其 cache 中没有缓存数据。这时候 CPU 就会在总线上发送一个 read invalidate 消息来请求数据,并试图独占该数据。CPU 可以通过收到的 read response 消息获取到数据,并等待所有的 invalidate acknowledge 消息,然后将状态设置为 modifie 。 - e
CPU需要执行一个原子的readmodify-write操作,并且其local cache中有read only的缓存数据(cacheline处于shared状态),这时候,CPU就会在总线上发送一个invalidate请求其他cpu清空自己的local copy,以便完成其独自霸占对该数据的所有权的梦想。同样的,该cpu必须收集所有其他cpu发来的invalidate acknowledge之后才能更改状态为 modified。 - f
在本cpu独自享受独占数据的时候,其他的cpu发起read请求,希望获取数据,这时候,本cpu必须以其local cacheline的数据回应,并以read response回应之前总线上的read请求。这时候,本cpu失去了独占权,该cacheline状态从Modified状态变成shared状态(有可能也会进行写回的动作)。 - g
这个迁移和f类似,只不过开始cacheline的状态是exclusive,cacheline和memory的数据都是最新的,不存在写回的问题。总线上的操作也是在收到read请求之后,以read response回应。 - h
需要发送invalidate以通知其他cpu相应数据将要失效,并等待其他cpu的回应消息(invalidate acknowledge)。 - i
其他的CPU进行一个原子的read-modify-write操作,但是,数据在本cpu的cacheline中,因此,其他的那个CPU会发送read invalidate,请求对该数据以及独占权。本cpu回送read response”和“invalidate acknowledge”,一方面把数据转移到其他cpu的cache中,另外一方面,清空自己的cacheline。 - j
cpu想要进行write的操作但是数据不在local cache中,因此,该cpu首先发送了read invalidate启动了一次总线transaction。在收到read response回应拿到数据,并且收集所有其他cpu发来的invalidate acknowledge之后(确保其他cpu没有local copy),完成整个bus transaction。当write操作完成之后,该cacheline的状态会从Exclusive状态迁移到Modified状态。 - k
本CPU执行读操作,发现local cache没有数据,因此通过read发起一次bus transaction,来自其他的cpu local cache或者memory会通过read response回应,从而将该 cache line 从Invalid状态迁移到shared状态。 - l
当cache line处于shared状态的时候,说明在多个cpu的local cache中存在副本,因此,这些cacheline中的数据都是read only的,一旦其中一个cpu想要执行数据写入的动作,必须先通过invalidate获取该数据的独占权,而其他的CPU会以invalidate acknowledge回应,清空数据并将其cacheline从shared状态修改成invalid状态。
该篇已完结
后续将在写一篇博文介绍在Java语言中某个关键字的底层是如何用到MESI协议以及内存屏障的。
author:YuShiwen
“了解高并发底层原理”,面试官:讲一下MESI(缓存一致性协议)吧相关推荐
- 并发编程实战-MESI缓存一致性协议
大家好,最近呢我对并发编程展现出了兴趣(没办法,别人都会你不会说不过去啊),然后我就要奋发图强学好并发编程,那么接下来让我们一起进入学习吧.我们在学习并发编程实战之前,应该先要了解一下我们的cpu缓存 ...
- 4.什么是MESI缓存一致性协议?怎么解决并发的可见性问题?
MESI一致性协议 小陈:老王,上一章你让我看看MESI一致性协议,我大概了解了一下. 老王:哦,来说说你对MESI一致性协议的理解 小陈:MESI协议也叫做缓存一致性协议,主要是用来进行协调多核CP ...
- 去大厂面试,说了没高并发经验,面试官还是抓着这个问!
我真服了,我tm现在满脑子都是"高并发",不得不说这个词真是技术圈的一个高频词. 如果不拿出这个说道说道就感觉技术非常欠缺似的.不过确实,高并发几乎是每个程序员都想拥有的经验. 原 ...
- 两个例子详解并发编程的可见性问题和有序性问题,通过volatile保证可见性和有序性以及volatile的底层原理——缓存一致性协议MESI和内存屏障禁止指令重排
1. 并发编程的可见性问题 2. 并发编程的有序性问题 3. 使用volatile关键字解决可见性问题 4. 可见性问题的本质--缓存不一致 因为cpu执行速度很快,但是内存执行速度相对于CPU很慢, ...
- 解秘 Node.js 单线程实现高并发请求原理,以及串联同步执行并发请求的方案
最近在做一个支持多进程请求的 Node 服务,要支持多并发请求,而且请求要按先后顺序串联同步执行返回结果. 对,这需求就是这么奇琶,业务场景也是那么奇琶. 需求是完成了,为了对 Node.js 高并发 ...
- 并发底层原理:线程、资源共享、volatile 关键字
并发底层原理:线程.资源共享.volatile 关键字 1.线程 1.1 定义任务 1.2 Thread 类 1.3 使用 Executor 1.4 从任务中产生返回值 1.6 优先级 1.7 后台线 ...
- 关于Spring底层原理面试的那些问题,你是不是真的懂Spring?
转载自 关于Spring底层原理面试的那些问题,你是不是真的懂Spring? 1.什么是 Spring 框架?Spring 框架有哪些主要模块? Spring 框架是一个为 Java 应用程序的开发 ...
- 多线程高并发 底层锁机制与优化的最佳实践——各种锁的分类 || synchronized 关键字 倒底锁的是什么东西?|| CAS与ABA问题||锁优化||轻量级锁一定比重量级锁的性能高吗
多线程高并发 底层锁机制与优化的最佳实践 各种锁的分类 加上synchronized 关键字,共享资源就不会出错 synchronized 关键字 倒底锁的是什么东西? synchronized 锁的 ...
- 聊聊高并发(五)理解缓存一致性协议以及对并发编程的影响
Java作为一个跨平台的语言,它的实现要面对不同的底层硬件系统,设计一个中间层模型来屏蔽底层的硬件差异,给上层的开发者一个一致的使用接口.Java内存模型就是这样一个中间层的模型,它为程序员屏蔽了底层 ...
最新文章
- 百度paddle学习笔记
- html漂浮广告随页面移动代码,JS漂浮广告代码,慢慢漂移的广告JS代码
- 新手java五子棋完整代码判断落子落在线上_Java初学者,编写小游戏五子棋的问题?...
- [20180102]11g的V$SORT_USAGE视图.txt
- c#快捷键(成为高手必备)
- Struts ActionForm简单理解
- 快速查询ABAP transport request lock status
- 【渝粤教育】电大中专幼儿园课程论 (1)作业 题库
- 如何将 byte[] 转换为 IntPtr?
- Go 语言初级教程之一[变量声明]
- [文档]CSS中文字体对照表
- linux zip unzip 命令
- 天堂2单机版服务器时间修改,如何制作最新L2J天堂2单机版源码服务端教程.doc
- 网页游戏开发入门教程一(webgame+design)
- 【Godot】项目结构设计
- js使用百度离线地图
- win11怎么关闭触控板?win11关闭触控板的三种解决方法
- 入门全栈Java程序员——CSS
- 怎样抢注到一个刚过期不久的域名?
- uni map 实时记录轨迹_无偏移、离线地图,追踪运动轨迹、户外旅行线路(GPS 轨迹)...