编译时内存重新排序会导致死锁吗?

时间:2014-12-13 11:17:30

标签: c++ c++11 concurrency stdatomic

在观看this谈论LLVM中C ++ 11原子的实现时,有一段代码

-- Initially --
int x = 0;
std::atomic<bool> flag1{false}, flag2{false};


-- Thread 1 --
x = 42;
flag1.store(true, std::memory_order_release);

while(!flag2.load(std::memory_order_acquire));
x = 43;


-- Thread 2 --
while(!flag1.load(std::memory_order_acquire));
printf("%d", x);
flag2.store(true, std::memory_order_release);

我认为这个代码数据没有竞争(正如发言人所说):它永远不会打印除42以外的任何内容。

但是,我不确定 它会打印42。我的问题是:不允许编译器在线程1中通过while循环重新排序存储,以便两个线程都会死锁吗?或者C ++ 11标准的哪个部分阻止了这种行为?

1 个答案:

答案 0 :(得分:0)

编译器必须永远不要将任何(外部可见)值的存储移动到释放栏之外,并且不得在读取栅栏上方移动读取。这是围栏的主要目的。

这里也可能涉及其他语义,例如,如果需要刷新缓存,释放围栏将刷新任何&#34;写入&#34;等待从这个CPU输出到主存储器。类似地,获取围栏将需要刷新所有或选定的区域,以便在下一次读取发出之前读入新值。

但是,所有现代CPU都在CPU之间具有连贯的内存,所以这不是问题 - 在某些不寻常/小型或旧CPU中可能存在一个问题,其中有一个缓存假定其他CPU不会读取相同的内容他们在缓存中的内存。如果您使用的是不一致的非统一处理器,那么缓存维护也会成为一个问题 - 您需要确保以正确的方式刷新缓存。同样,某些专业领域,但可能是多处理器系统中的一个重要因素。