この例が正しく同期されたプログラムである理由を理解しようとします。
a - volatile
Thread1:
x=a
Thread2:
a=5
競合するアクセスがあるため (a への書き込みと読み取りがあるため)、すべての順次整合性において、実行はそのアクセス間の先行発生関係でなければなりません。順次実行の 1 つを想定します。
1. x=a
2. a=5
1 が 2 の前に発生するのはなぜですか?
この例が正しく同期されたプログラムである理由を理解しようとします。
a - volatile
Thread1:
x=a
Thread2:
a=5
競合するアクセスがあるため (a への書き込みと読み取りがあるため)、すべての順次整合性において、実行はそのアクセス間の先行発生関係でなければなりません。順次実行の 1 つを想定します。
1. x=a
2. a=5
1 が 2 の前に発生するのはなぜですか?
1 が 2 の前に発生するのはなぜですか?
私はあなたの質問を100%理解しているとは言えません。
volatile 変数がa
あり、あるスレッドがそれから読み取り、別のスレッドが書き込みを行っている場合、それらのアクセスの順序はどちらの順序でもかまいません。これは競合状態です。JVM と Java メモリ モデル (JMM) によって何が保証されるかは、どちらの操作が最初に発生するかによって異なります。
書き込みが発生したばかりで、読み取りで更新された値が表示される可能性があります。または、読み取りの後に書き込みが発生する可能性があります。のいずれx
か5
または以前の値である可能性がありますa
。
すべての逐次一貫性実行は、そのアクセス間の事前発生関係でなければなりません
これが何を意味するのかわからないので、具体的にしようと思います。「関係の前に起こる」とは、同じ変数の読み取りの前にvolatile
、変数への以前のすべてのメモリ書き込みが完了したことが保証されることを意味します。しかし、この保証は、競合状態の対象となるvolatile
2 つの操作間のタイミングを説明するものではありません。volatile
リーダーは書き込みを確認したことが保証されますが、書き込みが読み取りの前に発生した場合に限ります。
これはかなり弱い保証だと思うかもしれませんが、ローカル CPU キャッシュを使用することでパフォーマンスが劇的に向上するスレッドでは、フィールドの値の読み取りは、中央メモリではなく、キャッシュされたメモリ セグメントから行われる可能性があります。この保証はvolatile
、スレッドがデータを適切に共有できるように、読み取りが発生したときにローカル スレッド メモリが無効化および更新されるようにするために重要です。
繰り返しますが、JVM と JMM は、 field から読み取る場合、読み取りの前に発生した同じフィールドへの書き込みがすべて表示されることを保証しvolatile
ます。a
書き込まれた値は適切に公開され、読み取りに表示されます。スレッド。ただし、この保証によって順序が決まるわけではありません。読み取りの前に書き込みを行う必要があるとは言いません。
いいえ、(同期順序で) 同じ変数の揮発性書き込みの前の揮発性読み取りは、必ずしも揮発性書き込みの前に発生するとは限りません。
これは、「先行発生関係によって順序付けられていない競合するアクセス」であるため、「データ競合」に陥る可能性があることを意味します。それが本当なら、ほぼすべてのプログラムにデータ競合が含まれています:) しかし、おそらく仕様のバグです。揮発性の読み取りと書き込みは、決してデータ競合と見なされるべきではありません。プログラム内のすべての変数が volatile である場合、すべての実行は単純に順次一貫性があります。http://cs.oswego.edu/pipermail/concurrency-interest/2012-January/008927.htmlを参照してください。