原子变量上下文中的总线锁定是什么?

The*_*ist 5 c++ multithreading mutex atomic bus

我使用 C++ 很长时间了,现在我开始学习汇编并学习处理器的工作原理(不仅仅是为了好玩,而且我必须作为测试程序的一部分)。在学习汇编时,我开始听到一些我在讨论多线程时在这里和那里听到的一些术语,因为我在科学计算中做过很多多线程。我正在努力获得完整的图片,我很感激帮助我扩大我的图片。

我了解到,最简单的总线就像一个多路复用器,然后是一个多路分解器。每端都以一个地址作为输入,以便将两端与一些外部组件连接起来。两端可以根据地址指向内存、显卡、RAM、CPU寄存器或其他任何东西。

现在开始我的问题:我一直听到人们争论是使用互斥锁还是原子来确保线程安全(我知道没有最终答案,这不是我的问题,但我的问题是关于比较)。例如,这里声称原子是如此糟糕,以至于它们会因为总线锁定而阻止处理器做体面的工作。

有人可以详细解释一下总线锁定是什么,以及为什么它不像互斥锁,而 AFAIK,互斥锁需要至少两个原子操作来锁定和解锁。

MSa*_*ers 5

“我了解到,总线最简单的形式就像一个多路复用器,后面跟着一个解复用器。每个末端”

嗯,这是不正确的。在最简单的形式中,不需要多路复用或多路分解。这只是两件事直接相互交谈。在不那么简单的情况下,总线可能连接三个或更多设备。在这种情况下,您开始需要总线地址,因为您不再可以谈论“另一端”。

现在,如果单个总线上有多个设备,它们通常无法同时通话。必须有某种机制来防止他们同时说话。然而,为了让所有设备能够共享该总线,它们必须能够轮流谁在与谁通话。总线锁定是一个广义术语,意味着与通常模式的任何偏差,在通常模式中,两个设备保留总线用于相互对话。

在 x86 内存总线的特定上下文中,这意味着在读取-修改-写入周期期间保持总线锁定(正如 Kerrek SB 在注释中指出的那样)。现在,这听起来像是一个带有 2 个设备(内存和 CPU)的简单总线,但 DMA 和多核芯片使这变得不那么简单。


Max*_*kin 5

来自英特尔® 64 和 IA-32 架构软件开发人员手册:

从 P6 系列处理器开始,当前LOCK缀作为指令的前缀并且被访问的内存区域在处理器内部缓存时,LOCK# 信号通常不会被断言。相反,只有处理器的缓存被锁定。在这里,处理器的缓存一致性机制确保操作是针对内存原子地执行的。

有特殊的非临时存储指令可以绕过缓存。所有其他加载和存储通常都通过缓存,除非内存页面被标记为不可缓存(如 GPU 或 PCIe 设备内存)。