题目
介绍下 MESI 协议
答案
MESI 协议主要是为了在引入高速缓存(CPU Cache)后,保证 CPU 缓存一致性。 ### Cache 写策略 数据写入 CPU Cache 之后,在什么时机才把 Cache 中的数据写回到内存呢?有两种常见的写入数据的方法: 1)**写直达**(*Write Through*):把数据同时写入内存和 Cache 中 写直达的缺点:无论数据在不在 Cache 里面,每次写操作都会写回到内存,这样写操作将会花费大量的时间,无疑性能会受到很大的影响 2)**写回**(*Write Back*):当发生写操作时,新的数据仅仅被写入 Cache Line 里,只有当修改过的 Cache Line「被换出」时才需要写到内存中,减少了数据写回内存的频率,这样便可以提高系统的性能。 ![](https://cs-wiki.oss-cn-shanghai.aliyuncs.com/img/image-20220630160220444.png) ### CPU 缓存一致性的问题 以一个含有两个 CPU Core 的 CPU 作为例子 假设 A 号核心和 B 号核心同时运行两个线程,都操作共同的变量 i(初始值为 0 )。 ![](https://cs-wiki.oss-cn-shanghai.aliyuncs.com/image-20230401165248245.png) 这时如果 A 号核心执行了 `i++` 语句的时候,为了考虑性能,使用了我们前面所说的写回策略,先把值为 `1` 的执行结果写入到 L1/L2 Cache 中,这个时候数据其实没有被同步到内存中的,因为写回策略,只有在 A 号核心中的这个 Cache Line 要被替换的时候,数据才会写入到内存里。 如果这时旁边的 B 号核心尝试从内存读取 i 变量的值,则读到的将会是错误的值,因为刚才 A 号核心更新 i 值还没写入到内存中,内存中的值还依然是 0。**这个就是所谓的缓存一致性问题,A 号核心和 B 号核心的缓存,在这个时候是不一致,从而会导致执行结果的错误。** ![](https://cs-wiki.oss-cn-shanghai.aliyuncs.com/image-20230401165501533.png) ### 保证 CPU 缓存一致性:MESI 协议 **MESI 协议就保证了 CPU 缓存一致性,是支持写回(write-back)缓存的最常用协议**。MESI 其实是 4 个标识 Cache Line 状态单词的开头字母缩写,分别是: - **Modified,已修改**:代表该 Cache Line 上的数据已经被更新过,但是还没有写到内存里 - **Exclusive,独占**:代表数据只存储在一个 CPU 核心的 Cache 里,而其他 CPU 核心的 Cache 没有该数据。这个时候,如果要向独占的 Cache 写数据,就可以直接自由地写入,而不需要通知其他 CPU 核心,因为只有你这有这个数据,就不存在缓存一致性的问题了,于是就可以随便操作该数据。 - **Shared,共享**:代表着相同的数据在多个 CPU 核心的 Cache 里都有,所以当我们要更新 Cache 里面的数据的时候,不能直接修改,而是要先向所有的其他 CPU 核心广播一个请求,要求先把其他核心的 Cache 中对应的 Cache Line 标记为「无效」状态,然后再更新当前 Cache 里面的数据。 - **Invalidated,已失效**:表示的是这个 Cache Line 里的数据已经失效了,不可以读取该状态的数据。