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

时间:2017-04-12 09:20:17

标签: c++ multithreading mutex atomic bus

我很长一段时间都在使用C ++,现在我开始学习汇编并了解处理器的工作原理(不仅仅是为了好玩,而且我必须作为测试程序的一部分)。在学习汇编时,我开始听到我在讨论多线程时听到的一些术语,因为我在科学计算中做了很多多线程。我很难全面了解,我很乐意帮助我扩大我的画面。

我了解到最简单形式的公共汽车就像multiplexer followed by a demultiplexer。每个端点都将地址作为输入,以便将两端连接到一些外部组件。根据地址,两端可以指向内存,图形卡,RAM,CPU寄存器或其他任何内容。

现在回答我的问题:我一直在听人们争论是否使用互斥或​​原子来保证线程安全(我知道没有最终的答案,这不是我的问题,但我的问题是关于比较) 。例如,Here声称原子是如此糟糕以至于它们会阻止处理器因为总线锁定而无法正常工作

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

3 个答案:

答案 0 :(得分:2)

“我了解到,最简单形式的总线就像多路复用器,然后是多路分解器。每个端点都是”

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

现在,如果您在一条总线上安装了多台设备,它们通常无法同时进行通话。必须有一些机制来阻止他们同时谈话。然而,对于能够共享该总线的所有设备,他们必须能够交替谁与谁交谈。 总线锁定作为一个广义术语意味着与通常模式的任何偏差,其中两个设备保留总线以进行相互对话。

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

答案 1 :(得分:2)

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

  

从P6系列处理器开始,当LOCK前缀作为指令前缀并且正在访问的存储区域在处理器内部缓存时,LOCK#信号通常不会被置位。相反,只锁定处理器的缓存。这里,处理器的缓存一致性机制确保操作以内存方式执行。

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

答案 2 :(得分:1)

使用多个资源进行访问时,需要使用总线。通常,不跨越高速缓存行且具有可缓存内存类型的锁不需要总线锁。核心将只要求该行是排他的,并且当其他核心尝试访问资源时可能会发送通知。

非可缓存内存类型将需要总线锁,因此未对齐的锁将跨越一个缓存行以及任何其他需要多个资源的事务。

如果未获取所有资源,则进程可能会死锁。当多个进程能够抢占资源,从而使任何一个进程都没有所有资源可以向前推进时,就会发生这种情况