缓存一致性协议(MESI)工作原理
计算器CPU多核缓存架构
在这种架构下,很难保证数据一致性,CPU1从主内存中读取数据,进行修改,并且更新到
缓存中,但是缓存中的数据什么时候更新到主内存的数据,并不知道,当CPU1从主内存中拿到
了数据(x=2),修改了数据(x=5),还没更新到主内存中,CPU2这时候也拿主内存中的数据(x=2,set
x=x+3=5),很明显,cpu2拿的并不是最新的数据。这就是缓存不一致问题针对这种问题,有两种
解决办法。
①:总线锁,对主内存中的数据加锁,当一个线程读取时,就会加锁,其他线程就不能读写
这个数据。总线锁的缺点就是效率低下。
②:缓存一致性协议,也就是说的MESI,目前大多数cpu就是采用的缓存一致性协议,于是就
有了以下的架构。
M:修改,该cache line有效,数据被修改了,和内存中的数据不一样,数据只存在于本cache中
E:独享、互斥,该cache line有效,数据和内存中的数据一致,数据只存在于本cache中'
S:共享,该cache line有效,数据和内存中的数据一致,数据存在于很多cache中
I:无效,该cache无效。
MESI是怎么保证缓存一直性的呢?举个栗子:
假设主内存中有一个变量x=1,当cpu1读取了之后,cpu1中就会有缓存变量x(E)就会有一个时刻监听(总线嗅探机制)去监听主 内存,,这时候,加入cpu2也读取了,那么cpu1中就会变成x(S),而cpu2中也会存在x(S),cpu2也会对主内存监听,这时候,当 cpu1对x做了修改,那么cpu1中就变成了X(M),当cpu通知了主内存之后,cpu1中就变成了X(E),而cpu2中则变成了X(I),于是 cpu2中的x就被抛弃,这时候会重新获取,重新获取之后,cpu1和2中都会变成X(S)。
那么假如两个线程同时修改了X,怎么办?
加入同时修改,当在一个指令周期内,会进行裁决,裁决胜利的就可以修改,失败的话,怎么处理看cpu,不同的cpu指令不 一 样。取决于指令(像java中,就有unsafe来处理)。
从主内存中,读取锁的最小单位是缓存行,加入一个数据的长度大于一个缓存行,这时候就会出现缓存行失效问题,当缓存行失 效,就会走总线加锁。