Multithreading 邻近单字节变量的原子写入

Multithreading 邻近单字节变量的原子写入,multithreading,x86,locking,atomic,Multithreading,X86,Locking,Atomic,假设,在一台多处理器机器上,有两个全局变量a和B,每个变量大小为一个字节,在内存中彼此相邻,两个CPU执行以下代码 中央处理器1: read A calculate new value write A 中央处理器2: read B calculate new value write B 只要看看物理上会发生什么,我们就可以预期,如果没有任何显式锁定,上述情况将是不正确的,因为A和B可能位于同一缓存线中,CPU 1需要读取整个缓存线,更改单个字节的值,然后再次写入缓存线;如果CPU 2对中间的

假设,在一台多处理器机器上,有两个全局变量a和B,每个变量大小为一个字节,在内存中彼此相邻,两个CPU执行以下代码

中央处理器1:

read A
calculate new value
write A
中央处理器2:

read B
calculate new value
write B
只要看看物理上会发生什么,我们就可以预期,如果没有任何显式锁定,上述情况将是不正确的,因为A和B可能位于同一缓存线中,CPU 1需要读取整个缓存线,更改单个字节的值,然后再次写入缓存线;如果CPU 2对中间的缓存线执行读-修改-写操作,则对B的更新可能会丢失。(我假设A和B的更新顺序无关紧要,我只关心确保更新不会丢失。)

但是x86保证这段代码是正确的。在x86上,只有当单个变量未对齐或大于CPU字大小时,对该变量的写入才会变成非原子变量


x86 CPU是否会自动在前端总线上执行额外锁定,以使这些单独的变量更新在没有显式锁定的情况下正常工作?

由于缓存一致性协议,此代码是正确的。当CPU1修改缓存线时,该行在CPU 2的缓存中无效,CPU 2无法写入B,必须等待(请参阅状态机)


因此不会丢失任何更新,也不需要总线锁

该规范是正确的,因为该标准提供了以下保证(1.7.3):

两个或多个执行线程可以访问单独的内存位置,而不会相互干扰

变量可能共享同一缓存线。这可能会导致错误共享,即每个核心在写入和删除时使缓存线无效 访问同一缓存线的其他内核必须从链中较高的内存中获取数据


这会减慢速度,但从正确性的角度来看,错误共享是不相关的,因为在没有同步的情况下仍然可以访问单独的内存位置。

这个问题没有任何特定的语言标记。您的引用与C++抽象机有关,但是抽象机器如何映射到底层目标处理器体系结构是编译器本身的实现细节。因此,虽然C++抽象机可以保证,但底层处理器可能会做其他操作。由代码生成器将抽象机器的语义映射到目标体系结构上。。这个从我的过滤器里漏掉了你能解释一下你为什么这么认为吗?如果没有缓存一致性,更新的缓存线将覆盖主内存中的旧缓存线,所以旧内容将丢失。当时我修复了这样的bug,这幅图怎么了?我的陈述是基于这样一个假设,即问题中的伪代码与C/C++内存模型有关。C++标准是以PAR为基础的。1.7.3(见我的答案)。你在哪个平台上修复这些错误?缓存一致性使CPU缓存之间的数据保持同步。在这种情况下,每个CPU只读取/写入自己的变量;如果该变量未与其他CPU同步,则该变量甚至可以工作。。但这几乎是一个没有意义的问题,因为没有缓存一致性的系统实际上是不存在的。啊,谢谢。我想它被问及一般的计算机体系结构主题,比如“当不同的CPU使用相同的缓存线时,硬件的哪一部分禁止完全无效的溢出”。即,在C++标准中没有前端总线。重要的是要知道,这不是“在前端总线上锁定”,而是每个缓存线粒度的支持。您在哪个平台上修复这些错误?它是INMOS transputer和Intel i860共享RAM。Transputer没有现代意义上的缓存,但i860有。