写点什么

MESI 缓存一致性协议

用户头像
胧月
关注
发布于: 4 小时前

1:在目前主流的计算机中,CPU 执行计算的主要流程如图所示



2:数据加载流程如下

  • 1 将需要的数据从磁盘家在到内存中

  • 2 将内存中的数据加载到缓存中(图中的 L1,L2,L3)

  • 3 CPU 从缓存中拿到数据进行计算

  • 4 将计算结果刷回缓存,并在一定的时间刷回内存

3:MESI 出现背景

 现在的CPU的一般都是多核,每个CPU都有自己独立的缓存,就是图中的L1,L2,L3, 如果这时候CPU1更新了数据,比如将a的值从1改成2,但是还没有刷回内存, 那么这时候CPU2从内存读取的a的值还是1,就出现了数据不一致的情况了复制代码
复制代码

4:对总线加锁

在Java程序中,为了线程安全我们一般都会选择加锁,比如Synchronized,Lock等, 但是对总线加锁会导致对其它数据的读写造成阻塞,整体性能下降复制代码
复制代码

5:MESI 的原理

MESI的原理就类似HashTable和ConcurrentMap的特性一样,一个是直接在整个方法加锁,一个是分段锁,MESI是针对某个缓存行进行加锁,它只会针对某个缓存行加锁,不会影响其它数据的读写复制代码
复制代码

6:MESI 协议解析

7:MESI 流程解析

  • 1: CPU1 将变量 a 从内存加载到自己的独立的缓存中,并将该变量 a 的状态设置为 E(独享)状态,并通过总线嗅探技术对内存中 a 的操作进行嗅探



  • 2:此时 CPU2 要读取变量 a,总线嗅探到这个操作后就会将 CPU1 中变量 a 的状态从 E(独享) 修改成 S(共享) 状态



  • 3:如果这时候 CPU1 要修改 a 的值了,那么此时 CPU1 中的 a 的状态就会从 S(共享)状态修改成 M(修改)状态,而 CPU2 中的变量 a 的状态会从 S(共享)状态修改成 I(无效),这时候如果说 CPU1 和 CPU2 同时要修改 a 的值怎么办??这时候 MESI 会从 CPU1 和 CPU2 中选择其中一个,并将 a 的状态修改成 M(修改),其它的都变成 I(无效)



  • 4:CPU1 将 a 修改后的值写回内存,并将 a 的状态修改成 E(独享)状态,后续其它 CPU 通过总线嗅探技术得知变量 a 的值已经被修改,就会从内存读取最新的值,并且 CPU1 和 CPU2 中 a 的状态就都会变成 S(共享状态)



  • 5:MESI 协议只能保证数据的可见性,并不能保证有序性原子性,所以不能只靠 MESI 来解决多线程中的安全问题

8:MESI 无效场景

  • 1 CPU 不支持缓存一致性协议

  • 2 MESI 是对单独一个缓存行进行加锁,此时如果这个数据的大小超出了一个缓存行的大小,那么也会无效

作者:baojh

链接:https://juejin.cn/post/7005454086988365838

来源:掘金


用户头像

胧月

关注

还未添加个人签名 2021.08.17 加入

还未添加个人简介

评论

发布
暂无评论
MESI缓存一致性协议