什么叫缓存一致性呢?
有了高速缓存的存在以后,每个 CPU 的处理过程是,
1、计算需要用到的数据缓存在 CPU 高速缓存中,
2、CPU进行计算时,直接从高速缓存中读取数据并且在计算完成
3、写入到缓存中。在整个运算过程完成后,
4、把缓存中的数据同步到主内存。
由于在多 CPU 种,每个线程可能会运行在不同的 CPU 内,并且每个线程拥有自己的高速缓存。
同一份数据可能会被缓存到多个 CPU 中,如果在不同 CPU 中运行的不同线程看到同一份内存
的缓存值不一样就会存在缓存不一致的问题,为了解决缓存不一致的问题,在 CPU 层面做了很多事情,
主要提供了两种解决办法
1. 总线锁
2. 缓存锁
总线锁和缓存锁
总线锁,在多 cpu 下,当其中一个处理器要对共享内存进行操作的时候
1、在总线上发出一个 LOCK#信号
2、这个信号使得其他处理器无法通过总线来访问到共享内存中的数据,总线锁把 CPU 和内存之间的通信锁住了
3、这使得锁定期间,其他处理器不能操作其他内存地址的数据,所以总线锁定的开销比较大
如何优化
最好的方法就是控制锁的保护粒度,我们只需要保证对于被多个 CPU 缓存的同一份数据是一致的。
所以引入了缓存锁,它核心机制是基于缓存一致性协议来实现的
缓存一致性协议
为了达到数据访问的一致,需要各个处理器在访问缓存时遵循一些协议,
在读写时根据协议来操作,常见的协议有MSI,MESI,MOSI 等。
MESI协议
M(Modify) 表示共享数据只缓存在当前 CPU 缓存中,并且是被修改状态,也就是缓存的数据和主内存中的数据不一致
E(Exclusive) 表示缓存的独占状态,数据只缓存在当前CPU 缓存中,并且没有被修改
S(Shared) 表示数据可能被多个 CPU 缓存,并且各个缓存中的数据和主内存数据一致
I(Invalid) 表示缓存已经失效
对于 MESI 协议,从 CPU 读写角度来说会遵循以下原则
CPU 读请求:缓存处于 M、E、S 状态都可以被读取,I 状态 CPU 只能从主存中读取数据
CPU 写请求:缓存处于 M、E 状态才可以被写,对于 S 状态的写,需要将其他 CPU 中缓存行置为无效才可写
MESI 优化带来的可见性问题
MESI 协议虽然可以实现缓存的一致性,但是也会存在一些问题
1、各个 CPU 缓存行的状态是通过消息传递来进行的,如果 CPU0 要对一个在缓存中共享的变量进行写入,
首先需要发送一个失效的消息给到其他缓存了该数据的 CPU。并且要等到他们的确认回执。CPU0 在这段时间都会处于阻塞状态
转载须注明
文章由 青涩知夏 编辑,转载请注明出处