2

这些天,我正在阅读有关内存栅栏和屏障的信息,以作为同步多线程代码和避免代码重新排序的一种方式。

我通常在 Linux 操作系统下用 C++ 开发,我boost大量使用库,但我找不到任何与之相关的类。你知道提升中是否存在栅栏的内存屏障,或者是否有办法实现相同的概念?如果没有,我可以看看什么好的图书馆?

4

4 回答 4

5

boost 中还没有低级内存屏障,但是有一个提议的 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 的栅栏。

于 2010-10-04T09:00:58.400 回答
1

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

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

我刚刚发现自己(适度地)需要可移植的内存屏障实现(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 内核文档中对内存屏障有很好的描述。

于 2012-02-09T11:52:44.430 回答
0

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

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

于 2010-10-03T20:44:08.270 回答
0

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

您可以通过调用来发出栅栏std::atomic_thread_fence。简而言之:

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

文档中有更多详细信息。

于 2019-08-21T06:46:37.487 回答