JDK5以降、JMMはhazards-beforeの概念を使用して、複数のスレッド間のメモリの可視性について詳しく説明しています。 JMMでは、ある操作の実行結果を別の操作で可視化する必要がある場合、2つの操作の間にhazards-beforeの関係がなければなりません。ここで言う2つの操作は、同じスレッド内でも、異なるスレッド間でもかまいません。
happens-before
happens-beforeの原則は非常に重要で、データ競合があるかどうかを判断する主な根拠となります。スレッド安全性はこの原則に依存し、並行環境における2つの操作の間に競合があるかどうかのすべての問題を解決します。例えば
i=1; // スレッド A j=i; // スレッド Bjは1に等しいですか?スレッドAの操作がスレッドBの操作の前に起こると仮定すると、スレッドBの実行後にj = 1が成立しなければならないと判断できます。happens-beforeの原理は次のように定義されます:
ある操作が他の操作より先に起こる場合、最初の操作の実行結果は2番目の操作から見えることになり、最初の操作は2番目の操作より先に実行されることになります。
2つの操作の間にhapens-beforeの関係が存在することは、必ずしもhapens-beforeの原則によって確立された順序で実行されなければならないことを意味しません。順番を入れ替えた結果が hapens-before の関係に従って実行した結果と同じであれば、この順番の入れ替えは違法ではありません。
最初のものは、プログラマの便宜のためのもので、このようにhapens-beforeの関係として理解することができます: AがBの前に起こる場合、Javaのメモリモデルは、プログラマに保証します: - Aの操作の結果はBに見えるようになり、AはBの順序で実行されることに注意してください。これは、Javaのメモリ・モデルがプログラマに対して行う保証にすぎません!実際には再順序付け不可能ではありません。
もう1つは、コンパイラとプロセッサの並び替えのための拘束原理です。コンパイラとプロセッサは、プログラムの実行結果を変えない限り、何でもできます。つまり、1つ目はプログラマ関係の便宜を図っているだけで、結果が変わらない限り、それが本当に並び替えかどうかは問題ではありません。
happens-before
プログラム順序規則:スレッド内の各操作は、そのスレッド内の後続の操作の前に発生します。
モニター・ロック・ルール:ロックのアンロックは、そのロックの後続のロックの前に起こります。
揮発性変数ルール:揮発性フィールドへの書き込みは、その揮発性フィールドの後続の読み取りよりも前に発生します。
start() 規則: スレッド A が ThreadB.start() 操作を実行する場合、スレッド A の ThreadB.start() 操作は、スレッド B の後続の操作よりも先に発生します。
join () のルール:スレッド A が ThreadB.join () 操作を実行して正常に返された場合、ThreadB.join () 操作が正常に返される前に、スレッド B の任意の操作がスレッド A で発生します。
プログラム割り込みルール:スレッドinterrupted()メソッドの呼び出しは、割り込み時間を検出する割り込みスレッドのコードに先行します。
オブジェクトのファイナライズ規則:オブジェクトの初期化の完了は、そのfinalize()メソッドの開始に先行します。
happens-beforeJMMとの関係
学習ソース Javaにおける並行プログラミングの技術
個人的な意見です。議論へようこそ、個人ブログ