はのは、この構造体を見てみましょう:C++ 11アトミック:なぜこのコードは機能しますか?
struct entry {
atomic<bool> valid;
atomic_flag writing;
char payload[128];
}
二つのトレッドAとBを同時にこの構造体をこのように(e
がentry
のインスタンスであるとする)アクセス:
if (e.valid) {
// do something with e.payload...
} else {
while (e.writing.test_and_set(std::memory_order_acquire));
if (!e.valid) {
// write e.payload one byte at a time
// (the payload written by A may be different from the payload written by B)
e.valid = true;
e.writing.clear(std::memory_order_release);
}
}
を、私はこのコードが正しいことを推測し、問題はありませんが、なぜそれが機能するのか理解したいと思います。 C++標準(29.3.13)を引用
:
実装は時間の妥当な量以内原子負荷 原子ストアが見えるようにすべきです。
これを念頭に置いて、スレッドAとBの両方がelse
ブロックに入るとします。このインターリーブは可能ですか?
- 両方
A
とB
valid
がfalse
A
あるwriting
フラグA
のロックを回転さB
開始writing
フラグを設定するので、else
分岐を入力している(valid
フラグを読み出しfalse
)、if
ブロックA
ペイロードを書き込みますA
有効フラグにtrue
を書き込みます。明らかに、A
再度valid
を読み取る場合は、読み取りなるtrue
A
はB
がB
writing
フラグは有効フラグ(false
)の失効値を読み取り、if
ブロックに入る設定writing
フラグをクリアB
ペイロードを書き込むB
書いたフラグB
上はwriting
フラグをクリア
私はこれが不可能であるが、それは「それができない理由?」実際に質問に答えるために来るとき、私はよく分からない願っています回答。ここに私の考えがあります。 読み取りに関連する書き込み前に書かれた
アトミック読み出し - 変更 - 書き込み操作が常に(変更の順で)最後の値 を読んでなければならない。(29.3.12)再び標準からの引用
-modify-writeオペレーション。
atomic_flag::test_and_set()
は、29.7.5で説明したアトミックリードモディファイライトです。私はvalid
フラグの古い値を読み取ることができません私はすべての副作用が原因と見なければならないので、その後、atomic_flag::test_and_set()
以来
は常に「新鮮値」を読み、私はstd::memory_order_acquire
メモリ順序でそれを呼んでいる、atomic_flag::clear()
コール(std::memory_order_release
を使用)の前にA
で指定します。
は私が修正アム?
明確化。私の全体的な推論(が間違っているか正しくは)は29.3.12に依存しています。私が今まで理解したところでは、atomic_flag
を無視すれば、valid
から古くなったデータを読むことはatomic
でも可能です。 atomic
は、すべてのスレッドに「常にすぐに見える」という意味ではないようです。あなたが読むことができる最大限の保証はあなたが読んだ値の一貫した順序ですが、あなたは新鮮なものを得る前に古いデータを読むことができます。幸運なことに、atomic_flag::test_and_set()
とすべてのexchange
操作はこの重要な機能を持っています。常に新鮮なデータを読み込みます。したがって、あなたがwriting
フラグ(valid
だけでなく)で取得/解放する場合にのみ、期待される動作が得られます。私のポイントが正しいかどうか分かりますか?
EDIT:私の元の質問は、質問のコアに比べた場合、あまりにも多くの注目を集め、次の数行が含まれています。私は、すでに与えられている回答との一貫性のためにそれらを残していますが、今質問を読んでいるなら、それらを無視してください。
atomic<bool>
とないプレーンなbool
というvalid
内の任意の点はありますか?さらに、それがatomic<bool>
であるべきならば、が発行しないメモリの最小注文制約は何ですか?else
枝valid
インサイド
C++ 11のメモリモデルは、可視性が最終的に発生する限り、順序が十分であるため、「可視性」ではなく「順序付け」の観点から考えます。 (私はあなたが@Grizzlyとの会話の後でこれを理解していると思うが、ここでそれを繰り返す気がする。) – Nemo