Suppose, on a multiprocessor machine, there are two global variables A and B, each one byte in size, located near each other in memory, and two CPUs executing the following code.
CPU 1:
read A
calculate new value
write A
CPU 2:
read B
calculate new value
write B
Just looking at what would tend to physically happen, we would expect the above would be incorrect without any explicit locking because A and B could be in the same cache line, and CPU 1 needs to read the entire cache line, change the value of a single byte and write the line again; if CPU 2 does its read-modify-write of the cache line in between, the update to B could be lost. (I'm assuming it doesn't matter what order A and B are updated in, I'm only concerned with making sure neither update is lost.)
But x86 guarantees this code is okay. On x86, a write to a single variable only becomes non-atomic if that variable is misaligned or bigger than the CPU word size.
Does an x86 CPU automatically carry out extra locking on the front side bus in order to make such individual variable updates, work correctly without explicit locking?
答案 0 :(得分:1)
由于缓存一致性协议,此代码是正确的。当CPU1修改高速缓存行时,该行在CPU 2的高速缓存中变为无效,并且CPU 2无法写入B并且必须等待(请参阅https://en.wikipedia.org/wiki/MESIF_protocol状态机)。
因此不会丢失更新,也不需要总线锁。
答案 1 :(得分:1)
代码是正确的,因为标准提供了以下保证(1.7.3):
两个或多个执行线程可以访问不同的内存位置而不会相互干扰。
变量可能共享同一个缓存行。这可能导致 false sharing ,即每个核心在写入时使高速缓存行无效 访问同一缓存行的其他核心必须从内存中获取更高的数据。
这会降低速度,但从正确的角度来看, false sharing 是无关紧要的,因为无需同步即可访问单独的内存位置。