C++"记忆障碍"的例子

use*_*112 8 c++ multithreading volatile

我正在阅读关于volatile关键字的这个问题的答案:

/sf/answers/173962421/

这个人说:

防止重新排序的解决方案是使用内存屏障,该内存屏障向编译器和CPU指示在该点上不能重新排序内存访问.在易失性变量访问周围放置这些障碍可确保即使非易失性访问也不会在易失性访问中重新排序,从而允许我们编写线程安全的代码.

但是,内存障碍还可以确保在达到屏障时执行所有挂起的读/写操作,因此它有效地为我们提供了我们自己需要的所有内容,从而使得volatile不必要.我们可以完全删除volatile限定符.

这个"内存障碍"在C++中是如何实现的?

编辑:

有人可以给出一个简单的代码示例吗?

qdi*_*dii 6

这非常依赖于硬件.从相当长的Linux内核内存屏障文档:

The Linux kernel has eight basic CPU memory barriers:

TYPE                MANDATORY               SMP CONDITIONAL
===============     ======================= ===========================
GENERAL             mb()                    smp_mb()    
WRITE               wmb()                   smp_wmb()
READ                rmb()                   smp_rmb()   
DATA DEPENDENCY     read_barrier_depends()  smp_read_barrier_depends()
Run Code Online (Sandbox Code Playgroud)

我们特别考虑其中一个:smp_mb().如果你打开asm/x86/um/asm/barrier.h,你会发现当CONFIG_SMP 定义时,

#define smp_mb()    mb()
Run Code Online (Sandbox Code Playgroud)

如果你向上滚动,你可以看到,根据平台,mb有不同的实现:

// on x86-32
#define mb()        alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
// on other platforms
#define mb()        asm volatile("mfence" : : : "memory")
Run Code Online (Sandbox Code Playgroud)

本主题讨论了有关这两件事之间差异的更多信息.我希望这有帮助.

  • 它们不是系统调用(顺便说一下,你可以通过运行`man 2 syscalls`找到所有系统调用).c ++编译器将用编译代码中的相应ASM指令替换`mb()`调用.您可以自己创建一个内存屏障,其中包括调用一些汇编指令,就像linux源代码一样. (4认同)

Pet*_*ker 5

在C++ 11中使用内存障碍是微不足道的:

std::atomic<int> i;
Run Code Online (Sandbox Code Playgroud)

所有访问i都将受到内存障碍的保护.