私は次のC++2011コードを持っています:
std::atomic<bool> x, y;
std::atomic<int> z;
void f() {
x.store(true, std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_release);
y.store(true, std::memory_order_relaxed);
}
void g() {
while (!y.load(std::memory_order_relaxed)) {}
std::atomic_thread_fence(std::memory_order_acquire);
if (x.load(std::memory_order_relaxed)) ++z;
}
int main() {
x = false;
y = false;
z = 0;
std::thread t1(f);
std::thread t2(g);
t1.join();
t2.join();
assert(z.load() !=0);
return 0;
}
私のコンピュータアーキテクチャクラスでは、このコードのアサートは常に真になると言われています。しかし、今それを徹底的に検討した後、私はそれがなぜそうなのか本当に理解できません。
私が知っていることについて:
- ' memory_order_release 'のあるフェンスは、それ以降に前のストアを実行することを許可しません
- ' memory_order_acquire 'のあるフェンスでは、その後のロードをその前に実行することはできません。
私の理解が正しければ、なぜ次の一連のアクションが発生しないのですか?
- t1の内部
y.store(true, std::memory_order_relaxed);
はと呼ばれます - t2は完全に実行され、「x」をロードすると「false」が表示されるため、ユニット内のzは増加しません。
- t1は実行を終了します
- メインスレッドでは、z.load()が0を返すため、アサートは失敗します
これは「取得」-「解放」ルールに準拠していると思いますが、たとえば、この質問のベストアンサー:私の場合と非常によく似たc ++ 11メモリフェンスを理解すると、私の場合のステップ1のようなものが示唆されます一連のアクションは「memory_order_release」の前に発生することはできませんが、その背後にある理由から詳細には触れません。
私はこれについてひどく戸惑っています、そして誰かがそれに光を当てることができれば非常にうれしいです:)