基于C ++ 11获取/发布语义,我有以下问题:
获取语义定义:编译器/ CPU不应重新排序在获取之前发生的获取之后发生的读取。 但是它可以将获取语句之后发生的写入重新排序到Acquire ??
之前发布语义定义:编译器/ CPU不应重新排序在发布之后发布之前发生的写入。 但是它可以将Release语句之前发生的读取重新排序到Release ??
之后示例:
atomic<int> i = 0, j = 0, x = 0;
i = 0;
j = x;
i = 20;
编译器/ CPU是否会将上述内容重新排序(优化)到以下内容:
原子i = 0,j = 0,x = 0;
i = 20;
j = x;
但是如果我们使用获取加载,编译器/ CPU是否会避免重新排序写入i(i = 20)??
原子i = 0,j = 0,x = 0;
i = 0;
atomic j = x.load(memory_order_acquire);
i = 20;
答案 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
带有atomicA
到a
的依赖关系,并且在依赖关系的情况下 - 即使代码中没有明确的排序 - 执行必须以保持该依赖关系的方式流动,在这种情况下,不会在加载之前对存储重新排序。