获取/释放语义重新排序

时间:2016-08-21 03:53:03

标签: c++ multithreading c++11 synchronization

基于C ++ 11获取/发布语义,我有以下问题:

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

之前

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

之后

示例:

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

i = 0;

j = x;

i = 20;
  1. 编译器/ CPU是否会将上述内容重新排序(优化)到以下内容:

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

    i = 20;

    j = x;

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

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

    i = 0;

    atomic j = x.load(memory_order_acquire);

    i = 20;

1 个答案:

答案 0 :(得分:0)

我认为你改变了获取/释放语义..
来自cpp reference

  

memory_order_acquire:[...]没有读取   当前线程可以在 此加载之前重新排序

     

memory_order_release:[...]当前线程中没有写入可以   在 此商店之后重新排序

关于你的问题:

  

但是它可以重新排序在获取语句之后发生的写入   到获得之前?   但是它可以重新排序发生的读取   在发布声明之前发布之后??

通常,是的,只要代码效果按原样进行而不重新排序,编译器和CPU可能会重新排序指令以使程序运行得更快。这就是为什么如果需要严格排序,我们明确使用原子+记忆顺序和锁。

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

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

虽然代码中没有明确规定的排序(轻松的原子=按照你的意愿重新排序),atomicB带有atomicAa的依赖关系,并且在依赖关系的情况下 - 即使代码中没有明确的排序 - 执行必须以保持该依赖关系的方式流动,在这种情况下,不会在加载之前对存储重新排序。