用来保证cache一致性的协议,
多核cpu中,多核会共享数据,
对同一个变量,各自有保存一个副本,也会对副本进行更新
为了都能读到真实最新的值, cpu之间又不像java里面的多线程, 可以到公共的地方,就是堆里面 ,用堆里面一个对象来作为锁,好像一个布告栏一样,集中式控制
cpu之间是像互联网一样分布式的, 只能靠协议交流
这就是缓存一致协议MESI协议
这个协议, 规定了 cpu对各自的高速缓存读写时 要发到总线和其他cpu交流的信息, 还规定了 缓存条目的状态
简而言之, 就是状态是无效,就群发请求拿有效值, 要写就群发通知(独占就省了),先让其他失效
每个核都监听其他cache的读写操作,根据自己和其他的读写 改变缓存条目的Flag
local是本核读写,remote是其他核读写
- local read 除了I变S/E 其他不变
- local write 都变M
- remote read I不受影响 其他变S
- remote write 都变 I
M(Modified):我修改了数据, 内存和其他cpu都不知道,现在的值是啥
E(Exclusive):就我数据和内存一致, 其他cpu都没有效副本
S(Shared):内存有这行数, 其他cpu可能 也有这数据
I(Invalid): 这数据无效,是旧数据了, 因为有其他cpu写了更新的
木兮清扬 的CSDN 博客
例子
- cpu1要读数据, 发现那条缓存条目已经失效了(I状态),
就往总线发读请求,
其他cpu收到这个读请求,会往总线发读响应: 现在有效的Data Block(不止是cpu1请求的那个值),
cpu1收到整块数据以后, 后 存起来就好了, 状态设为 S
准备发 读响应 的那行 状态是 M
就是说 本cpu刚改过 这块数据, 但是其他cpu不知道, 内存也不知道,现在的值,
那么, 它可能会在 发 读响应以前, 先把数据 给存到 主内存,
发生读响应以后, 这行数据 状态设为 S要写数据
如果状态是 E/M, 说明我就是最新数据, 其他cpu这条数据都是I, 那我直接写就行了
如果是 S I, 我需要先发 失效, 让其他cpu把这条变成I, 收到其他cpu的 失效ack 后, 我把状态变成E, 才能开始写, 改完以后 把状态变成 M
弱点
只是有这个缓存一致性协议, 根本不会有可见性问题
但是, 坏处是, 要请求 等响应, 这个过程漫长, 浪费时间
因此 就有 写缓冲器
和无效化队列
就是针对此的优化, 优化就会带来问题