English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

JavaメモリモデルJMMの学習の感想

時にはコンパイラやプロセッサの最適化により、ランタイムが私たちの予想とは異なることがあります。そのため、Javaはコンパイラやプロセッサに対していくつかの制限を設け、JAVAメモリモデル(JMM)がこれらを抽象化し、コードを書く際には多くの低レベルの詳細を考慮する必要がなく、ただJMMのルールに従ったプログラムを書けば、その実行結果は常に正しいと保証されます。

JMMの抽象構造

Javaでは、すべてのインスタンス、静的変数はヒープメモリに格納され、ヒープメモリはスレッド間で共有できます。これはまた、共有変数局部変数、メソッドの定義引数、例外処理引数はスタック上にありますが、スタックメモリはスレッド間で共有されません。

また、コンパイラやプロセッサの最適化により、共有変数の可见性問題が発生することがあります。これは特にマルチコアプロセッサ(multi-プロセッサ(processor)では、スレッドが異なるプロセッサ上で実行されることがありますが、プロセッサ間のキャッシュ不一致は、共有変数の可见性問題を引き起こします可能性がありますが、同じ変数に対して異なる値が2つのスレッドで見られます。

JMMはこれらのハードウェアの最適化を各スレッドがローカルメモリを持つという抽象にまとめます。共有変数を読み書きする必要がある場合、メインメモリからローカルメモリにコピーします。共有変数を書き込む場合、まずローカルメモリに書き込み、その後ある時点でメインメモリに反映します。再度共有変数を読み込む場合、ローカルメモリからのみ読み取ります。

これにより、スレッド間のコミュニケーションは二つのステップで行われます:

書き込みスレッド:ローカルメモリをメインメモリに反映読み込みスレッド:更新された値を読み取るメインメモリから

これにより、書き込み-読み込みと読み込みの間に遅延があります:ローカルメモリがいつメインメモリに反映されるべきか?これにより可见性問題が発生し、異なるスレッドが同じ共有変数を異なる値として見ることができます。

happens-before

文字通りに見るとhappens-beforeの意味は「その前に発生」。これはJavaがプログラムの実行順序に対して制定したルールであり、同期を実現するにはこのルールに従う必要があります。これにより、プログラマーは正しい同期プログラムを書くだけで十分であり、happens-beforeは、実行結果が間違いないことを保証します。

Aが起こる-before Bは、AがBの前に実行されることを示すだけでなく、Aの実行結果がBに可见であることを意味し、これが可见性を保証します。

Aが起こる-before Bの前にAが実行される必要はありません。AとBが交互に実行され、結果が正しい場合、コンパイラやプロセッサが最適化および重排序を許可されます。したがって、プログラムの結果が正しい限り、コンパイラやプロセッサがどのように最適化し、どのように重排序を行おうとも問題ありません。

happens-beforeルール

プログラムの順序ルール:あるスレッドでは、前の操作がhappens-beforeの後の操作のロックルール:同じロックに対して、解锁がhappens-volatile変数の書き込みがhappensのルール:before加锁-beforeの後ろに任意の読み取り操作がこのvolatile変数に発生する伝播性:Aが起こります-before B、Bが起こります-before C、則Aが起こります-before 線程Bを開始する start()ルール:線程AがThreadB.start()を実行した場合、ThreadB.start()がhappensします-before 線程Bのあらゆる操作 join()ルール:線程AがThreadB.join()を実行した場合、線程Bのすべての操作がhappensします-before ThreadB.join()

以下の例はhappensの理解に役立ちます-before

double pi = 3.14; //A
double r = 1.0; //B
double area = pi * r *r; //C

ここに3つのhappensがあります-before関係、ルール1、2これはプログラムの順序ルール、ルール3これは伝播則から導出されています:

Aが起こる-Bの前に Bが起こる-C Aが起こる前に-Cの前に

CはA、Bに依存しており、AとBは互いに依存していません。したがって、AとBが重排序された場合でも、実行結果は変更されません。この重排序はJMMが実行しています。

以下の2つの実行順序の結果はすべて正しいです。

以上が、Java メモリモデル(JMM)に関する学習ノートの全てです。さらに質問がある場合は、下記のコメント欄で讨论してください。あなたの「呐喊教程」へのサポートに感謝します。

声明:本文の内容はインターネットから取得しており、著作権者に帰属します。インターネットユーザーが自発的に貢献し、自己でアップロードしたものであり、本サイトは所有権を有しません。また、人工的な編集処理もなく、関連する法的責任も負いません。著作権侵害を疑われる内容がある場合は、メールを送信していただければ幸いです:notice#oldtoolbag.com(メールを送信する際には、#を@に置き換えてください。報告を行い、関連する証拠を提供してください。一旦確認がついたら、本サイトは即座に侵害を疑われるコンテンツを削除します。)

おすすめ