缓存一致性问题

缓存一致性问题

缓存一致性问题 #

所谓缓存一致性,就是保证同一个数据在每个 CPU 的私有缓存(一般为 L1 Cache)中副本是相同的。考虑下面的例子:

global sum = 0
// Thread1:
sum += 3
// Thread2:
sum += 5

假设 Thread1 由 CPU 核 P1 执行,Thread2 由 P2 执行,那么 P1、P2 的私有缓存和主存的状态可能出现下表所示的情况:

在这个表里,脏是缓存块的一个标识位,用来表示缓存中的数据有没有被改写,如果该缓存块的内容被修改,并且还没有同步到主存,就称它为脏的;

sum 对于 Thread1 和 Thread2 是共享的。初始状态 sum 的值为 0,Thread1 将 sum 加 3,Thread2 将 sum 加 5。正常来说,我们期望内存中的 sum 值是 8。但实际两个线程执行结束后,内存中的 sum 的取值根据缓存状态的传播情况,就会有不同的取值。

上表中展示了一种内存中 sum 值为 5 的操作序列。但是,第 5 步和第 6 步的顺序有可能会对调,所以 sum 值还有可能是 3。如果第 3 步,P1 的缓存中的值能被正确地传播到 P2,那么 P2 的 sum 值就为 8,所以最终内存中的值还有可能是 8。

通过上面的例子我们可以看出,为了保证缓存一致性,必须解决两个问题,分别是写传播(第 3 步)和事务串行化(第 5 和第 6 步)。

写传播是指,一个处理器对缓存中的值进行了修改,需要通知其他处理器,也就是需要用到“写更新”或者“写无效”策略。

事务串行化是指,多个处理器对同一个值进行修改,在同一时刻只能有一个处理器写成功,必须保证写操作的原子性,多个写操作必须串行执行。

那怎样解决写传播所带来的缓存一致性问题呢?那就需要缓存一致性协议,前面提到缓存中的值同步给主存有两种策略(写回和写直达),而且,不同的写策略,对应不同的缓存一致性协议。

Viewpoint #

From #