在他的 talk 即将结束时关于内存屏障(fences),他举了下面的例子(注意:global
is not of atomic type):
// thread 1 // thread 2
widget *temp = new widget();
global = temp;
global->do_something();
global->do_something_else();
后来他说我们应该有如下全栅栏:
// thread 1 // thread 2
widget *temp = new widget();
XX mb(); XXXXXXXXXXXXXXXXXXXXX
global = temp;
temp2 = global;
XX mb(); XXXXXXXXXXXXXXXX
temp2->do_something();
temp2 = global;
XX mb(); XXXXXXXXXXXXXXXX
temp2->do_something_else();
我想知道为什么在线程 1 中需要屏障? global
取决于 temp
编译器不会移动 global = temp;
以上施工temp
反正。我能想到的需要内存屏障的一个原因是语句 global=temp;
可以在 new widget()
的构建过程中以某种方式完成然后线程 2 会看到一个部分构造的 global
.是否有可能分配给 global
被安排在 build 新的中间widget
?还是其他什么原因造成的内存障碍?
同样在线程 2 中,在 temp2->do_something();
之后不需要另一个屏障吗? ?与当前转换后的形式一样,以下语句在执行期间仍然可以重新排序:
temp2 = global;
XX mb(); XXXXXXXXXXXXXXXX
temp2 = global;
temp2->do_something();
XX mb(); XXXXXXXXXXXXXXXX
temp2->do_something_else();
这不是您想要的,因为现在您只调用一个 temp2
上的成员函数。而不是从 global
中读取新值在执行 do_something_else()
之前.
如果在线程 2 中不可能进行这样的重新排序,那么如果 temp2->do_something();
,为什么我们首先需要线程 2 中的屏障?无法在 temp2 = global;
之前重新订购.
最佳答案
I wonder why in thread 1 you need a barrier? global depends on temp and compiler wouldn't move global = temp; above the construction of temp anyway.
它与 temp
内部成员的初始化有关。由于 CPU 缓存和重新排序,这里没有内存屏障 global
可能有新的 temp
地址,但 temp
指向的内存可能显示为未初始化.
至于第二个问题,显然
temp2->do_something();
temp2 = global;
不能重新排序为
temp2 = global;
temp2->do_something();
因为它会在非常不同的对象上做一些事情!
关于c++ - 赫伯萨特原子武器 "Why Standalone Fences are Suboptimal",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36434392/