コンパイラとプロセッサの最適化により、ランタイムが想像したものとは異なる場合があります。このため、Javaはコンパイラとプロセッサにいくつかの制限を課しています。 Javaメモリモデル(JMM)はこれらを抽象化して、コードを書くときにそれほど多くの根本的な詳細を検討する必要がないようにし、「プログラムを書くためにJMMルールに従う限り、実行結果は正しい」ことを保証します。
JMMの抽象構造
Javaでは、すべてのインスタンスと静的変数がヒープメモリに保存され、スレッド間で共有できます。この部分は共有変数とも呼ばれます。ローカル変数、メソッド定義パラメーター、および例外処理パラメーターがスタック上にあり、スタックメモリはスレッド間で共有されていません。
ただし、コンパイラとプロセッサの最適化により、共有変数には可視性の問題が発生します。たとえば、マルチプロセッサでは、異なるプロセッサでスレッドを実行でき、プロセッサ間で矛盾するキャッシュは共有変数に視界の問題を引き起こします。 2つのスレッドが同じ変数の異なる値を見る可能性があります。
JMMは、これらのハードウェアによって作成された最適化を、各スレッドにローカルメモリがあることを抽象化します。共有変数を読み書きする必要がある場合は、メインメモリからローカルメモリにコピーをコピーします。共有変数を作成するときは、最初にローカルメモリに書き込み、将来のいつかメインメモリに更新します。共有変数が再度読み取られると、ローカルメモリからのみ読み取ります。
このようにして、スレッド間の通信には2つのステップが必要です。
スレッドを書き込む:ローカルメモリを更新してスレッドを読む:メインメモリから更新された値を読む
このようにして、ライティングと読書の間に遅延があります。地元のメモリはいつメインメモリにリフレッシュされますか?これにより、可視性の問題が発生し、異なるスレッドには異なる共有変数が表示される場合があります。
前に起こる
文字通り起こる - 以前は「これの前に起こる前」を意味します。これは、Javaがプログラムの実行の順序で定式化するルールであり、同期に従う必要があります。このようにして、プログラマーは正しい同期プログラムを書き出すだけで、実行中の結果が間違っていないことを保証する前に起こります。
Aは、Bの前に起こることを意味します。AがBの前に実行されることを意味するだけでなく、Aの実行結果がBに表示され、可視性が保証されます。
bの前に、aはBの前に実行する必要はありません。ABが交互に交互になり、実行結果がまだ正しい場合、コンパイラとプロセッサは再注文を最適化できます。したがって、プログラムの結果が正しい限り、コンパイラとプロセッサがどのようにそれを最適化し、並べ替えるかに問題はありません。それはすべて良いことです。
事前に行われます
プログラムシーケンスルール:スレッドでは、前の操作の後に操作ロックルールが発生します。同じロックのロックを解除して、揮発性ドメインルールをロックしてロックします。操作のトランシテンシー:Aが発生する-b、B、bはCの前に発生します。
次の例は、前に起こることを理解するのに役立ちます
double pi = 3.14; // adouble r = 1.0; // bdoubleエリア= pi * r * r; // c
以前に行われる3つの関係があります。ルール1と2はプログラムの順序ルールであり、ルール3は推移的なルールから派生しています。
BBが起こる前に起こる - caが起こる前に起こる前にc
CはAとBに依存しますが、AもBもそれに依存しません。したがって、aとbが再注文されたとしても、実行結果は変わりません。この並べ替えでは、JMMが実行されています。
次の2つの実行シーケンスが正しいです。
上記は、JavaメモリモデルJMMの学習についてお客様のためにコンパイルしたすべてのコンテンツです。その他の質問については、以下にメッセージを残してください。 wulin.comへのご支援ありがとうございます。