看懂这篇,才能说了解并发底层技术 (2)

在多线程进行共享变量访问时,因为各个线程执行的处理器上的高速缓存中都会保存一份变量的副本数据,这样就会有一个问题,那当一个副本更新后怎么保证其它处理器能马上的获取到最新的数据。这其实就是缓存一致性的问题,其本质也就是怎么防止数据的脏读。

为了解决这个问题,处理器间出现了一种通信机制,也就是缓存一致性协议(Cache Coherence Protocol)。

MESI是什么

缓存一致性协议有很多种,MESI(Modified-Exclusive-Shared-Invalid)协议其实是目前使用很广泛的缓存一致性协议,x86处理器所使用的缓存一致性协议就是基于MESI的。

我们可以把MESI对内存数据访问理解成我们常用的读写锁,它可以使对同一内存地址的读操作是并发的,而写操作是独占的。所以在任何时刻写操作只能有一个处理器执行。而在MESI中,一个处理器要向内存写数据时必须持有该数据的所有权。

MESI将缓存条目的状态分为了Modified、Exclusive、Shared、Invalid四种,并在此基础上定义了一组消息用于处理器的读、写内存操作。如图:

看懂这篇,才能说了解并发底层技术

MESI的四种状态

所以MESI其实就是使用四种状态来标识了缓存条目当前的状态,来保证了高速缓存内数据一致性的问题。那我们来仔细的看下四种状态

Modified :

表示高速缓存中相应的缓存行内的数据已经被更新了。由于MESI协议中任意时刻只能有一个处理器对同一内存地址对应的数据进行更新,也就是说再多个处理器的高速缓存中相同Tag值得缓存条目只能有一个处于Modified状态。处于此状态的缓存条目中缓存行内的数据与主内存包含的数据不一致。

Exclusive:

表示高速缓存相应的缓存行内的数据副本与主内存中的数据一样。并且,该缓存行以独占的方式保留了相应主内存地址的数据副本,此时其他处理上高速缓存当前都不保留该数据的有效副本。

Shared:

表示当前高速缓存相应缓存行包含相应主内存地址对应的数据副本,且与主内存中的数据是一致的。如果缓存条目状态是Shared的,那么其他处理器上如果也存在相同Tag的缓存条目,那这些缓存条目状态肯定也是Shared。

Invalid:

表示该缓存行中不包含任何主内存中的有效数据副本,这个状态也是缓存条目的初始状态。

MESI处理机制

前面说了那么多,都是MESI的基础理论,那么,MESI协议到底是怎么来协调处理器进行内存的读写呢?

看懂这篇,才能说了解并发底层技术

其实,想协调处理必然需要先和各个处理器进行通信。所以MESI协议定义了一组消息机制用于协调各个处理器的读写操作。

我们可以参考HTTP协议来进行理解,可以将MESI协议中的消息分为请求和响应两类。处理器在进行主内存读写的时候会往总线(Bus)中发请求消息,同时每个处理器还会嗅探(Snoop)总线中由其他处理器发出的请求消息并在一定条件下往总线中回复响应得响应消息。

针对于消息的类型,有如下几种:

Read : 请求消息,用于通知其他处理器、主内存,当前处理器准备读取某个数据。该消息内包含待读取数据的主内存地址。

Read Response: 响应消息,该消息内包含了被请求读取的数据。该消息可能是主内存返回的,也可能是其他高速缓存嗅探到Read 消息返回的。

Invalidate: 请求消息,通知其他处理器删除指定内存地址的数据副本。其实就是告诉他们你这个缓存条目内的数据无效了,删除只是逻辑上的,其实就是更新下缓存条目的Flag.

Invalidate Acknowledge: 响应消息,接收到Invalidate消息的处理器必须回复此消息,表示已经删除了其高速缓存内对应的数据副本。

Read Invalidate: 请求消息,此消息为Read 和 Invalidate消息组成的复合消息,作用主要是用于通知其他处理器当前处理器准备更新一个数据了,并请求其他处理器删除其高速缓存内对应的数据副本。接收到该消息的处理器必须回复Read Response 和 Invalidate Acknowledge消息。

Writeback: 请求消息,消息包含了需要写入主内存的数据和其对应的内存地址。

了解完了基础的消息类型,那么我们就来看看MESI协议是如何协助处理器实现内存读写的,看图说话:

举例:假如内存地址0xxx上的变量s 是CPU1 和CPU2共享的我们先来说下CPU上读取数据s

高速缓存内存在有效数据时:

看懂这篇,才能说了解并发底层技术

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wssjfg.html