【发布时间】:2016-04-05 18:36:28
【问题描述】:
在他的 talk 关于内存屏障(栅栏)的结尾,他给出了以下示例(注意:global 不是原子类型):
// 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。在构建新的widget 的过程中是否可以安排分配给global?还是内存屏障是其他原因造成的?
同样在线程 2 中,在temp2->do_something(); 之后你不需要另一个屏障吗?与当前转换的形式一样,以下语句在执行过程中仍然可以重新排序:
temp2 = global;
XX mb(); XXXXXXXXXXXXXXXX
temp2 = global;
temp2->do_something();
XX mb(); XXXXXXXXXXXXXXXX
temp2->do_something_else();
这不是你想要的,因为现在你只在一个temp2 上调用成员函数,而不是在执行do_something_else() 之前从global 读取一个新值。
如果线程 2 中不可能进行这种重新排序,那么如果 temp2->do_something(); 不能在 temp2 = global; 之前重新排序,为什么我们首先需要线程 2 中的障碍。
【问题讨论】:
标签: c++ multithreading