为了解决内存的可见性问题,cpu主要提供了两种解决方案:总线锁和缓存锁
1、总线锁和缓存锁
总线锁
CPU与外部所有部件的通信都需要通过总线进行操作,当cpu核去访问主存数据时,向总线上发送一个LOCK#信号锁定总线,当一个处理器往总线上输出LOCK#信号时,其它处理器的请求将被阻塞,此时该处理器此时独占共享内存。
锁总线,其它CPU对内存的读写请求都会被阻塞,直到锁释放,因为锁总线的开销比较大,后来的处理器都采用锁缓存替代锁总线,在无法使用缓存锁的时候会降级使用总线锁
缓存锁
相比总线锁,缓存锁降低了锁粒度,为了达到数据访问一致性,需要CPU在访问高速缓存时遵循一些协议,在存取数据时根据协议来操作,常见的协议有MSI,MESI,MOSI等,最常见的就是MESI协议。
要解决缓存一致性问题,首先要解决的是多个CPU核心之间的数据传播问题,常见的解决方案是总线嗅探(Bus Snooping)。
总线嗅探机制:把所有读写请求都通过总线广播给所有的CPU核心,各个CPU核心去嗅探这些请求,再根据本地的情况进行响应。
基于总线嗅探机制,可以分成很多种不同的缓存一致性协议,最常用的就是MESI协议
2、MESI协议
缓存行是高速缓存操作的基本单位,在Intel的CPU上一般是64个字节
在MESI协议中每个**缓存行**
有四种状态:
状态 | 说明 |
---|---|
M:被修改的(Modified) | 该缓存行有效,数据只在本cpu有缓存,且数据和主存不一致,数据被修改过 |
E:独享的(Exclusive) | 该缓存行有效,数据只在本cpu有缓存,且数据和主存一致 |
S:共享的(Shared) | 该缓存行有效,数据在多个cpu中有缓存,且数据和主存一致 |
I:无效的(Invalid) | 该缓存行无效,可能有其他cpu更改了该缓存行 |
![image.png](https://cdn.nlark.com/yuque/0/2021/png/1911003/1630490498675-93c3439a-a7ef-4185-84d2-70acd0c03ddf.png#clientId=u83954e09-09aa-4&from=paste&height=283&id=u7e62b979&margin=%5Bobject%20Object%5D&name=image.png&originHeight=565&originWidth=1166&originalType=binary&ratio=1&size=302872&status=done&style=none&taskId=u9b9af5ce-cb12-4f4d-98c3-ec22ad4caaa&width=583)
![image.png](https://cdn.nlark.com/yuque/0/2021/png/1911003/1630490448969-7d25ab98-a7e3-48b1-8755-5d543b2e06e9.png#clientId=u83954e09-09aa-4&from=paste&height=291&id=uf8d23b6f&margin=%5Bobject%20Object%5D&name=image.png&originHeight=582&originWidth=1161&originalType=binary&ratio=1&size=326240&status=done&style=none&taskId=u05aef8dc-0a63-4672-bc78-ce4f9796278&width=580.5)
MESI协议中把所有读写请求都通过总线广播给所有的CPU核心,各个CPU核心去嗅探这些请求,再根据本地的情况进行响应,缓存行状态会相应的改变。
Local Read表示本内核读本Cache中的值,Local Write表示本内核写本Cache中的值,Remote Read表示其它内核读其它Cache中的值,Remote Write表示其它内核写其它Cache中的值