内存屏障和互斥锁

Posted

技术标签:

【中文标题】内存屏障和互斥锁【英文标题】:Memory Barriers and Mutexes 【发布时间】:2014-09-11 00:50:44 【问题描述】:

给定两个线程之间的通用消息传递模式:

Thread-A                  Thread-B
-------------------       ---------------------
LockMutex(M1)
Get memory for Msg
  from shared resource
UnlockMutex(M1)

set Msg attributes (content)
(note: is *NOT* performed
 within a critical section--
 once the Msg's contents
 have been set, no other
 writes to the Msg 
 is performed)

LockMutex(M1)
place pointer of Msg
  within Thread-B's
  message queue.
UnlockMutex(M1)

notify Thread-B
  of new Msg
-------------------       ---------------------
                          LockMutex(M1)
                          extract pointer to Msg from
                            queue.
                          UnlockMutex(M1)

                          read contents of Msg
                          (note: Thread-B only *READS*
                           the contents of Msg)

问:如果'M1'是一个通用互斥体,当使用C++或C来实现软件时,Thread-B 总是是否保证有正确的'Msg'内容? 问:这种模式对于操作系统和/或处理器配置的某些组合是否不能正常工作? (我主要关注 Linux、Windows、Mac OS X、VxWorks、Green Hills 和 Micrium 等操作系统)

我的理解(可能不正确)是通过锁定和/或解锁互斥锁“M1”实现的关键部分将导致执行内存屏障/栅栏指令,这将确保处理器/核心缓存的一致性;因此 Thread-B 保证读取 'Msg' 的正确内容。但是,我很难找到表明上述“一般模式”是正确的权威文档。

【问题讨论】:

内存模型是编程语言的一个属性(或者在较低级别,是 CPU 的一个特性)。这个问题只能在特定内存模型的上下文中回答,因此在目前的形式下是无法回答的。 我认为要回答您的问题,您必须知道 CPU 的类型,即“弱”与“强”内存模型,然后您的代码使用的是哪个运行时。尽管如果您使用的是 Java,JVM 在所有架构中都有一个非常具体的内存模型,这让我相信 CPU 类型对您的问题并不重要。 @Ken Mumme:您想要的权威文档是C or C++ standard(分别)。在C11 中,相关部分是5.1.2.35.1.2.4(内存模型),以及7.177.26(标准库组件)。在C++11 中,相关部分是1.91.10(内存模型),以及2930(标准库组件)。总的来说,这个问题太宽泛了; C 和 C++ 是不同的语言,您问题中的伪代码可以有多种解释方式。 【参考方案1】:

在一般意义上,描述的“消息传递模式”对于所有平台不是“线程安全的”;但是,对于某些平台(例如单处理器单核,或某些具有强缓存一致性的多核处理器,例如 Intel/AMD x86-64),上述模式可以工作......但应该避免,因为不符合 C++11 内存模型。

【讨论】:

Will work + not conforming 对我来说没有意义。 即,它不是 platform independent 模式(由于不符合 C++11 内存模型);但是,如果处理器使用强大的缓存一致性协议,它将在某些平台上运行(例如,大多数基于 Intel/AMD x86-64 的系统)。 我没有很好地表达我的观点。关键是不符合标准的 c++ 代码永远不会可靠地工作。在上面的示例中,编译器可以生成代码,将消息数据有效地复制到寄存器中以提高性能,并且更新只更新内存,而不是寄存器,因此诸如强缓存一致性之类的特定于平台的保证无济于事。只有编译器扩展才能使不符合标准的 c++ 代码正常工作,而不是硬件保证。

以上是关于内存屏障和互斥锁的主要内容,如果未能解决你的问题,请参考以下文章

在 C 中使用互斥锁和屏障进行线程同步

盲猜原子变量内存屏障内存模型锁之间的关系

使用互斥量和信号量的屏障实现

Linux 内核 内存管理优化内存屏障 ④ ( 处理器内存屏障 | 八种处理器内存屏障 | 通用内存屏障 | 写内存屏障 | 读内存屏障 | 数据依赖屏障 | 强制性内存屏障 |SMP内存屏障 )

Linux 内核 内存管理优化内存屏障 ④ ( 处理器内存屏障 | 八种处理器内存屏障 | 通用内存屏障 | 写内存屏障 | 读内存屏障 | 数据依赖屏障 | 强制性内存屏障 |SMP内存屏障 )

如何在没有内存屏障的情况下实现 InterlockedIncrement