假设我的服务器程序有两个在不同内核上运行的线程(T1和T2)。两者都通过网络从单个外部客户端提供RPC。发生以下操作序列:
foo
初始化为零foo
设置为42 foo
,写入缓存在其核心的L1(非主存储器)中foo
foo
并看到它为零foo
为零。这违反了外部一致性。
这实际上是否会发生,或者在执行将ACK发送回客户端的I / O时是否存在T1缓存的隐式刷新?(步骤4)?
答案 0 :(得分:3)
在x86和x64系列上,所有缓存都是连贯的,即使两个线程不共享相同的缓存单元,你也会在T2上得到42。
您的思想实验可以进一步减少到2种情况:两个线程共享相同的缓存单元(多核)或不共享(多CPU)。
当他们共享一个缓存单元时,T1和T2都将使用相同的缓存,因此他们都会看到42而没有与内存同步。
如果不共享高速缓存(即,多CPU),则ISA要求高速缓存单元被同步,并且这对于软件是透明的。两个线程都会在同一地址看到42。这种同步虽然引入了一些开销,但是现在多核设计是首选(除了缓存昂贵的原因)。
答案 1 :(得分:3)
在步骤3,在T1修改值之前,它获取缓存行为“exclusive”,这意味着它不存在于任何其他线程的缓存中,并将缓存行状态设置为“modified”。
在步骤6,T2在其高速缓存中没有值,因此当它获取该值时,高速缓存一致性协议在T1的高速缓存中找到修改的行。高速缓存行的状态在T1的高速缓存和T2的高速缓存中都设置为“共享”。
答案 2 :(得分:2)
在x86上,缓存保持一致性以确保不会出现这样的问题。
第一部分是每个缓存跟踪它所拥有的每一行的状态 1 。如果(使用你的例子)一个数据同时保存在两个缓存中,一个写入它,它会将其缓存行设置为“已修改”状态,并向另一个CPU发送信号告诉它将用于保存相同数据的缓存行设置为“无效”状态。
难题的第二部分是每个CPU“窥探”所有内存事务(通过其他CPU或通过总线主控PCI设备),以便当其他人试图读取其缓存中的数据时“看到”。当发生这种情况时,它会强制暂停该事务,将数据从其缓存写入内存,然后在数据写入后继续执行事务,以便获取当前数据。