1

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 標準のどの部分がそのような動作を防いでいるのでしょうか?

4

1 に答える 1

0

コンパイラは、リリース フェンスを超えて (外部から見える) 値のストアを移動してはならず、取得フェンスを超えて読み取りを移動してはなりません。これがフェンスの主な目的です。

ここには他のセマンティクスも含まれる可能性があります。たとえば、キャッシュをフラッシュする必要がある場合、リリース フェンスは保留中の「書き込み」をこの CPU からメイン メモリにフラッシュします。同様に、取得フェンスは、次の読み取りが発行される前に新しい値が読み込まれるように、すべてまたは選択した領域をフラッシュする必要があります。

ただし、最新のすべての CPU は CPU 間で一貫したメモリを備えているため、これは問題ではありません。他の CPU が同じメモリを読み取らないことを前提とするキャッシュを備えた一部の異常/小型または古い CPU で問題になる可能性があります。キャッシュ。コヒーレントではない不均一なプロセッサを使用している場合、キャッシュのメンテナンスも問題になります。キャッシュが正しい方法でフラッシュされていることを確認する必要があります。これもやや特殊な領域ですが、マルチプロセッサ システムでは重要な要素になる可能性があります。

于 2014-12-13T12:01:58.007 に答える