缓存一致性协议
操作系统的CPU和内存并不是直接交互操作的。我们的CPU有一级缓存,CPU直接操作一级缓存,由一级缓存和内存进行交互。
当然,有的CPU有二级缓存,甚至三级缓存等。实际上,大概二十年前,一级缓存是直接和内存交互的,现在,一般是二级缓存和内存直接通讯。
每个CPU都有一级缓存,但是,我们却无法保证每个CPU的一级缓存数据都是一样的。
所以同一个程序,CPU进行切换的时候,切换前和切换后的数据可能会有不一致的情况。那么这个就是一个很大的问题了。
如何保证各个CPU缓存中的数据是一致的。就是CPU的缓存一致性问题。
一种处理一致性问题的办法是使用Bus Locking(总线锁)。当一个CPU对其缓存中的数据进行操作的时候,往总线中发送一个Lock信号。
这个时候,所有CPU收到这个信号之后就不操作自己缓存中的对应数据了,当操作结束,释放锁以后,所有的CPU就去内存中获取最新数据更新。
但是用锁的方式总是避不开性能问题。总线锁总是会导致CPU的性能下降。所以出现另外一种维护CPU缓存一致性的方式,MESI。
MESI是保持一致性的协议。它的方法是在CPU缓存中保存一个标记位,这个标记位有四种状态:
- M: Modify,修改缓存,当前CPU的缓存已经被修改了,即与内存中数据已经不一致了
- E: Exclusive,独占缓存,当前CPU的缓存和内存中数据保持一致,而且其他处理器并没有可使用的缓存数据
- S: Share,共享缓存,和内存保持一致的一份拷贝,多组缓存可以同时拥有针对同一内存地址的共享缓存段
- I: Invalid,实效缓存,这个说明CPU中的缓存已经不能使用了
CPU的读取遵循下面几点:
- 如果缓存状态是I,那么就从内存中读取,否则就从缓存中直接读取。
- 如果缓存处于M或E的CPU读取到其他CPU有读操作,就把自己的缓存写入到内存中,并将自己的状态设置为S。
- 只有缓存状态是M或E的时候,CPU才可以修改缓存中的数据,修改后,缓存状态变为M。
这样,每个CPU都遵循上面的方式则CPU的效率就提高上来了。