2
プログラマーレベルのC ++ std :: atomicでは何が保証されますか?
私はに関するいくつかの記事、講演、stackoverflowの質問を聞いて読みましstd::atomicたが、私はそれをよく理解していることを確認したいと思います。MESI(または派生した)キャッシュコヒーレンシプロトコル、ストアバッファー、キューの無効化などで遅延が発生する可能性があるため、キャッシュライン書き込みの可視性とまだ少し混乱しています。 私はx86がより強力なメモリモデルを持っていることを読みました。キャッシュの無効化が遅れると、x86は開始された操作を元に戻すことができます。しかし、私は今、プラットフォームに関係なく、C ++プログラマーとして何を想定すべきかについてのみ興味があります。 [T1:スレッド1 T2:スレッド2 V1:共有アトミック変数] std :: atomicは、 (1)変数でデータ競合は発生しません(キャッシュラインへの排他的アクセスのおかげ)。 (2)使用するmemory_orderに応じて、(バリアを使用して)順次整合性が発生することが保証されます(バリアの前、バリアの後、またはその両方)。 (3)T1のアトミック書き込み(V1)の後、T2のアトミックRMW(V1)はコヒーレントになります(そのキャッシュラインはT1に書き込まれた値で更新されます)。 しかし、キャッシュコヒーレンシープライマーの言及として、 これらすべての意味は、デフォルトで、ロードが古いデータをフェッチできることです(対応する無効化リクエストが無効化キューに置かれていた場合)。 それで、次は正しいですか? (4)std::atomicT2がT1のアトミックwrite(V)の後にアトミックread(V)の「古い」値を読み取らないことを保証しません。 (4)が正しいかどうかの質問:T1のアトミック書き込みが遅延に関係なくキャッシュラインを無効にする場合、アトミックRMW操作がアトミック読み取りではなく無効化が有効になるのをT2が待機しているのはなぜですか? (4)が間違っている場合の質問:スレッドは実行時に「古くなった」値を読み、「それが見える」のはいつですか? 回答ありがとうございます アップデート1 だから私はそのとき(3)について間違っていたようです。次のインターリーブを想像してください。最初のV1 = 0の場合: T1: W(1) T2: R(0) M(++) W(1) この場合、T2のRMWはW(1)の後に完全に発生することが保証されていますが、それでも「古い」値を読み取ることができます(私は間違っていました)。これによると、atomicは完全なキャッシュコヒーレンシを保証せず、順次一貫性のみを保証します。 アップデート2 (5)この例を想像してみてください(x = y = 0でアトミックです): T1: x = 1; T2: y = 1; T3: if (x==1 && y==0) print("msg"); …