c++ - 获取/释放语义重新排序

标签 c++ multithreading c++11 synchronization

基于C++11的acquire/release语义,我有以下问题:

Acquire 语义定义:编译器/CPU 不应将发生在 Acquire 之后的读取重新排序为发生在 Acquire 之前。 1. 但是它可以将 acquire 语句之后发生的写入重新排序到 Acquire 之前吗??

Release 语义定义:编译器/CPU 不应将发生在 Release 之前的写入重新排序为发生在 Release 之后。 2. 但是它能否将Release 语句之前发生的读取重新排序到Release 之后??

例子:

atomic<int> i = 0, j = 0, x = 0;

i = 0;

j = x;

i = 20;
  1. 编译器/CPU 会将上面的内容重新排序(优化)为以下内容:

    原子 i = 0, j = 0, x = 0;

    我 = 20;

    j = x;

  2. 但是如果我们使用获取加载,编译器/CPU 是否会避免重新排序写入 i (i=20) ??

    原子 i = 0, j = 0, x = 0;

    我 = 0;

    原子 j = x.load(memory_order_acquire);

    i = 20;

最佳答案

我认为你切换了获取/释放语义..
来自 cpp reference :

memory_order_acquire: [...] no reads in the current thread can be reordered before this load.

memory_order_release: [...] no writes in the current thread can be reordered after this store.

关于您的问题:

But can it reorder the writes that happen after the acquire statement to before the Acquire??
But can it reorder the reads that happen before the Release statement to after the Release??

一般来说,是的,只要代码效果保持原样,没有重新排序,编译器和CPU可能会重新排序指令,使程序运行得更快。这就是为什么如果需要严格排序,我们会明确使用原子 + 内存顺序和锁。

阻止 CPU/编译器重新排序的一般问题是依赖性,例如,请看下面的示例:

int a = atomicA.load(std::memory_order_relaxed);
a += 10;
atomicB.store(a,std::memory_order_relaxed);

尽管代码中没有明确说明排序(宽松的原子 = 按您的意愿重新排序),atomicB 通过 a 携带 atomicA 的依赖项>,并且在依赖项的情况下——即使代码中没有明确说明顺序——执行必须以保留该依赖项的方式进行,在这种情况下,不要在加载之前重新排序存储。

关于c++ - 获取/释放语义重新排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39060704/

相关文章:

c++ - 如何最好地实现 GIF 加载类?

c++ - 在屏幕上绘制图像后背景发生变化

c++ - 阶乘函数不适用于大数

c++ - 构造多个线程以获得最佳性能的正确方法是什么?

c++ - C/C++混合编程 : gdb segmentation fault frequently

java - 多线程实例化一次vs每个线程

c++ - char vs wchar_t vs char16_t vs char32_t (c++11)

c++ - std::unique_ptr 与自定义自由操作结合使用

java - 在服务中配置线程池大小

c++ - 使用多线程在c++中生成mandelbrot镜像。没有加速?