我现在正在阅读有关内存屏障和障碍的内容,以此来同步多线程代码并避免代码重新排序。
我通常在Linux OS下使用C ++进行开发,并且我大量使用boost
库,但我无法找到与之相关的任何类。你知道在增强中是否存在栅栏的记忆障碍,或者是否有办法实现相同的概念?如果不是我可以看看哪个好的图书馆?
答案 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中有更多详细信息。