我知道std :: memory_order枚举提供了内存防护但我需要确定每个std :: memory_order枚举元素提供的防护。 下面我解释,因为我理解每个std :: memory_order枚举元素:
关于前4个元素,我不确定。 但是关于最后两个元素,我什么都不知道。
任何人都知道这件事吗?
另外,我需要知道编译器在使用std :: atomic或std :: atomic_flag时放置内存栅栏的位置?
据我所知,使用带有原子的栅栏意味着应用栅栏并执行操作。我对吗? 例如:
atomic.load(std::memory_order_acquire);
表示应用memory_order_acquire fence并以原子方式加载数据?
答案 0 :(得分:2)
任何人都知道这件事吗?
当然,有各种各样的来源,例如C++ Reference:
memory_order_relaxed - 宽松的操作:没有对其他读取或写入施加同步或排序约束,只保证此操作的原子性。
memory_order_consume - 具有此内存顺序的加载操作会对受影响的内存位置执行使用操作:在此加载之前,可以重新排序当前线程中取决于当前加载的值的读取或写入。在当前线程中可以看到对释放相同原子变量的其他线程中的数据相关变量的写入。在大多数平台上,这只会影响编译器优化。
memory_order_acquire - 具有此内存顺序的加载操作会对受影响的内存位置执行获取操作:在此加载之前,不能对当前线程中的读取或写入进行重新排序。在当前线程中可以看到释放相同原子变量的其他线程中的所有写入。
memory_order_release - 具有此内存顺序的存储操作执行释放操作:在此存储之后,不能对当前线程中的读取或写入进行重新排序。当前线程中的所有写入在获取相同原子变量的其他线程中都是可见的,并且带有依赖关系到原子变量的写入在消耗相同原子的其他线程中变得可见。
memory_order_acq_rel - 具有此内存顺序的读取 - 修改 - 写入操作既是获取操作,也是释放操作。当前线程中的内存读取或写入不能在此存储之前或之后重新排序。在修改之前,其他发布相同原子变量的线程中的所有写入都是可见的,并且修改在获取相同原子变量的其他线程中可见。
memory_order_seq_cst - 具有此内存顺序的加载操作执行获取操作,存储执行释放操作,读取 - 修改 - 写执行获取操作和释放操作,以及单个存在总顺序,其中所有线程以相同的顺序观察所有修改。
请同时查看atomic<> Weapons presentation by Herb Sutter,其中解释了很多。
另外,我需要知道编译器放置内存栅栏的位置
这取决于架构。在某些体系结构上,它是一个无操作,有些是指令前缀,在某些体系结构上它将是加载/存储之前/之后的特殊指令。
有一篇名为"Memory Barriers: a Hardware View for Software Hackers"的论文,如果您感兴趣,可以分析许多架构的障碍。
例如:
atomic.load(std::memory_order_acquire);
表示应用memory_order_acquire fence并以原子方式加载数据?
这也取决于架构,但对于获取障碍,我会说完全相反:我们加载一个变量,然后我们确保在加载之前没有进一步的读/写,即放一个栅栏。
但在某些平台上,它可能是单处理器指令。例如,在ARM上有一个加载获取(LDA)和存储释放(STL)指令。