C ++中的内存栅栏/障碍:是否会增强或其他库有它们?

时间:2010-10-03 20:07:40

标签: multithreading boost boost-thread memory-barriers

我现在正在阅读有关内存屏障和障碍的内容,以此来同步多线程代码并避免代码重新排序。

我通常在Linux OS下使用C ++进行开发,并且我大量使用boost库,但我无法找到与之相关的任何类。你知道在增强中是否存在栅栏的记忆障碍,或者是否有办法实现相同的概念?如果不是我可以看看哪个好的图书馆?

4 个答案:

答案 0 :(得分:5)

升级中没有低级别的内存障碍,但是有一个提议的boost.atomic库提供它们。

编译器提供自己的内部函数或库函数,例如gcc的__sync_synchronize()_mm_mfence()用于Visual Studio。

C ++ 0x库提供原子操作,包括std::atomic_thread_fence形式的内存栅栏。虽然自V4.4以来gcc提供了各种形式的C ++ 0x原子,但V4.4或V4.5都不包括这种形式的栅栏。我的(商业)just::thread库提供了C ++ 0x原子的完整实现,包括g ++ 4.3和4.4的围栏,以及Microsoft Visual Studio 2005,2008和2010。

答案 1 :(得分:1)

需要内存障碍的地方是避免在SMP环境中使用内核同步机制 - 通常是出于性能原因。

在任何内核同步操作中存在隐式内存屏障(例如,信令信号量,锁定和解锁突变)和内容切换以防止数据一致性危害。

我刚刚发现自己需要(适度)便携式内存屏障实现(ARM和x86),并且还发现linux源代码树是最好的源代码。 Linux具有mb()rmb()wmb()宏的SMP变体 - 在某些平台上,这些变量导致比非SMP变体更具体(并且可能成本更低)的障碍。
这似乎不是x86特别是ARM所关注的问题,尽管两者都以相同的方式实现。

这是我从linux头文件(适用于ARMv7和非古老x86 / x64处理器)中拼凑而成的内容

#if defined(__i386__ ) || defined(__x64__)

#define smp_mb()    asm volatile("mfence":::"memory")
#define smp_rmb()   asm volatile("lfence":::"memory")
#define smp_wmb()   asm volatile("sfence" ::: "memory")
#endif

#if defined(__arm__)

#define dmb() __asm__ __volatile__ ("dmb" : : : "memory")

#define smp_mb()    dmb()
#define smp_rmb()   dmb()
#define smp_wmb()   dmb()
#endif

当然,涉及内存障碍的随之而来的风险是所产生的代码实际上无法测试,任何产生的错误都会模糊不清,难以重现竞争条件:/

顺便提一下,Linux kernel documentation中有很好的内存障碍描述。

答案 2 :(得分:0)

有一个boost::barrier类/概念,但它有点高级。说到这,为什么你需要一个低水平的障碍?同步原语应该足够了,不应该吗?并且它们应该在必要时使用内存屏障,直接或间接通过其他较低级别的原语。

如果你仍然认为你需要一个低级实现,我知道没有实现障碍的类或库,但Linux内核中有一些特定于实现的代码。在mb()中搜索rmb()wmb()include/asm-{arch}/system.h

答案 3 :(得分:0)

现在,在2019年, C ++标准库的几乎所有实现都应使用C ++ 11围栏。标题ist <atomic>

您可以致电std::atomic_thread_fence发出围栏。简而言之:

  • std::atomic_thread_fence(std::memory_order_release);确保没有任何存储操作移到调用之后。 (所有副作用都将对其他线程可见。)
  • std::atomic_thread_fence(std::memory_order_acquire);确保在调用之前不会移动任何加载操作。 (其他线程的所有副作用将变得可见。)

documentation中有更多详细信息。