ホームページ  >  記事  >  Java  >  写真と文章で詳しく解説! Javaメモリモデルとは何ですか

写真と文章で詳しく解説! Javaメモリモデルとは何ですか

WBOY
WBOY転載
2022-03-22 18:00:411582ブラウズ

この記事では、java に関する関連知識を提供します。主に、メモリ モデルの存在理由、同時プログラミング、メモリ領域とハードウェア メモリの関係など、メモリ モデルに関する関連事項を紹介します。待ってください、それが皆さんのお役に立てば幸いです。

写真と文章で詳しく解説! Javaメモリモデルとは何ですか

推奨学習:「java チュートリアル

面接では、面接官はよく次のように尋ねます。「Java とは何か教えてください。 「メモリモデル(JMM)?」 』

インタビュアーは大喜びで、この質問を暗記したばかりでした: 「Java メモリは主に 5 つの主要なブロックに分かれています: ヒープ、メソッド領域、仮想マシン スタック、ローカル メソッド スタック、PC レジスタ、バラバラ... "

面接官は知ったかぶりで微笑み、一筋の光を明らかにしました。「わかりました、今日の面接はここが先です。戻って通知を待ちます。」

一般的に、「待つ」というフレーズを聞くと、通知用」の可能性が高いインタビューです。とにかくカッコいいです。なぜ?面接官が概念を誤解していたため、面接官は JMM をテストしようとしましたが、面接官は JavaMemory というキーワードを聞くとすぐに、八本足のエッセイを暗唱し始めました。 Java メモリ モデル (JMM) と Java ランタイム メモリ領域の間には大きな違いがあります。立ち去らずに読み続けてください。すべて読むと約束してください。

1. メモリ モデルが必要なのはなぜですか?

この質問に答えるには、まず従来のコンピューター ハードウェア メモリ アーキテクチャを理解する必要があります。さて、絵を描き始めます。

1.1. ハードウェア メモリ アーキテクチャ

写真と文章で詳しく解説! Javaメモリモデルとは何ですか
(1)CPU

コンピューター室に行ったことのある生徒は、通常、複数のサーバーが大規模なサーバーで構成されていることを知っています。これは、複数の CPU または複数のコアが同時に (同時に) 動作できることを意味します。 Java を使用してマルチスレッド タスクを開始する場合、各 CPU がスレッドを実行する可能性が高く、タスクは特定の瞬間に実際に同時に実行されます。 (2)CPU レジスタ

CPU レジスタは CPU レジスタです。 CPU レジスタは CPU 内に統合されており、レジスタに対する演算の実行効率はメイン メモリに対する演算よりも数桁高くなります。

(3)CPU キャッシュ メモリ

CPU キャッシュ メモリは CPU のキャッシュであり、レジスタと比較して、通常は L2 二次キャッシュにもなります。メモリの読み出し速度はハードディスクと比較すると非常に効率が良いですが、それでもCPUとは桁違いなので、そのためにCPUとメインメモリの間に多値キャッシュが導入されています。バッファリングの。

(4) メイン メモリ

メイン メモリはメイン メモリであり、L1 および L2 キャッシュよりもはるかに大きくなります。

注: 一部のハイエンド マシンには、L3 レベル 3 キャッシュもあります。

1.2. キャッシュの一貫性の問題

メイン メモリと CPU プロセッサの計算能力の間には桁違いのギャップがあるため、従来のシステムではキャッシュがメイン メモリとして導入されます。コンピュータのメモリ アーキテクチャ。CPU とプロセッサの間のバッファに、CPU がよく使用するデータをキャッシュに置き、演算が完了した後、CPU が演算結果をメイン メモリに同期します。

キャッシュを使用すると、CPU とメイン メモリのレートの不一致の問題は解決されますが、キャッシュの一貫性の問題という別の新しい問題も発生します。


マルチ CPU システム (またはシングル CPU マルチコア システム) では、各 CPU コアが独自のキャッシュを持ち、同じメイン メモリ (メイン メモリ) を共有します。複数の CPU の演算タスクが同じメイン メモリ領域に関係する場合、CPU は演算のためにデータをキャッシュに読み込むため、それぞれのキャッシュ データに不整合が生じる可能性があります。 写真と文章で詳しく解説! Javaメモリモデルとは何ですか
したがって、各 CPU はキャッシュにアクセスするときに特定のプロトコルに従い、データの読み取りおよび書き込み時にそのプロトコルに従って動作し、共同してキャッシュの一貫性を維持する必要があります。このようなプロトコルには、MSI、MESI、MOSI、および Dragon Protocol が含まれます。

1.3. プロセッサの最適化と命令の並べ替え

パフォーマンスを向上させるために、CPU とメインメモリの間にキャッシュが追加されますが、マルチスレッドの同時実行では

キャッシュが発生する可能性があります。シナリオの一貫性の問題

。 CPU の実行効率をさらに向上させる方法はありますか?答えは、プロセッサの最適化です。

プロセッサ内のコンピューティング ユニットを最大限に活用するために、プロセッサは入力コードを順不同で実行します。これがプロセッサの最適化です。

プロセッサがコードを最適化することに加えて、多くの最新のプログラミング言語コンパイラも同様の最適化を実行します。たとえば、Java のジャストインタイム コンパイラ (JIT) は命令の並べ替えを実行します。


写真と文章で詳しく解説! Javaメモリモデルとは何ですか

プロセッサの最適化は、実際には並べ替えの一種です。要約すると、並べ替えは次の 3 つのタイプに分類できます。
  • コンパイラによる最適化された並べ替え。コンパイラは、シングルスレッド プログラムのセマンティクスを変更せずに、ステートメントの実行順序を再配置できます。
  • 命令レベルの並列並べ替え。最新のプロセッサは、命令レベルの並列処理を使用して、複数の命令をオーバーラップして実行します。データの依存関係がない場合、プロセッサはステートメントが機械語命令に対応する順序を変更できます。
  • メモリ システムの並べ替え。プロセッサはキャッシュと読み取りおよび書き込みバッファを使用するため、ロードおよびストア操作が順序どおりに実行されていないように見える可能性があります。

2. 同時プログラミングの問題

上記では、ハードウェア関連の多くのことについて言及しました。一部の学生は少し混乱しているかもしれません。このような大きな円を経た後、これらのことは次のとおりです。 Java メモリ モデルは重要ですか? とは関係ありません。心配しないで、ゆっくりと下を見てみましょう。

Java の並行性に精通している学生は、「可視性の問題」、「原子性の問題」、および「順序付けの問題」という 3 つの問題についてよく知っている必要があります。これら 3 つの問題をより深いレベルで見ると、実際には、前述の「キャッシュの一貫性」、「プロセッサの最適化」、および「命令の並べ替え」によって引き起こされます。

写真と文章で詳しく解説! Javaメモリモデルとは何ですか
キャッシュの一貫性の問題は、実際には可視性の問題です。プロセッサの最適化は原子性の問題を引き起こす可能性があり、命令の並べ替えは順序付けの問題を引き起こす可能性があります。それらはすべてつながっていると思いますか?

解決すべき問題は常に存在します。その解決策は何でしょうか?まず、単純で大雑把な方法を考えました。キャッシュを強制終了し、CPU がメイン メモリと直接対話できるようにすると、可視性の問題が解決します。プロセッサの最適化と命令の並べ替えを無効にすると、アトミック性と順序付けの問題が解決されますが、これは以前に戻ります。一夜にして解放されることは、明らかに望ましくないことです。

そこで技術部門の先輩たちは、物理マシン上に一連のメモリ モデルを定義して、メモリの読み取りおよび書き込み操作を標準化することを考えました。メモリ モデルは主に、同時実行性の問題を解決するために プロセッサの最適化を制限する メモリ バリアを使用する という 2 つの方法を使用します。

3. Java メモリ モデル

同じ一連のメモリ モデル仕様でも、言語が異なると実装に多少の違いがある可能性があります。次に、Java メモリ モデルの実装原理に焦点を当てます。

3.1. Java ランタイム メモリ領域とハードウェア メモリの関係

JVM を知っている学生は、JVM ランタイム メモリ領域が断片化され、スタックやヒープなどに分割されていることを知っています。 , これらは、JVM によって定義される論理概念です。従来のハードウェア メモリ アーキテクチャには、スタックとヒープの概念がありません。
写真と文章で詳しく解説! Javaメモリモデルとは何ですか
この図から、スタックとヒープはキャッシュとメイン メモリの両方に存在するため、この 2 つに直接の関係がないことがわかります。

3.2. Java スレッドとメイン メモリの関係

Java メモリ モデルは多くのことを定義する仕様です:

  • すべての変数はメイン メモリに格納されます。メモリ メインメモリ内。
  • 各スレッドにはプライベート ローカル メモリ (ローカル メモリ) があり、スレッドの読み取り/書き込み共有変数のコピーが保存されます。
  • スレッドによる変数の操作はすべてローカル メモリで実行する必要があり、メイン メモリを直接読み書きすることはできません。
  • 異なるスレッドは、互いのローカル メモリ内の変数に直接アクセスできません。

テキストを読むのは退屈すぎるので、別の絵を描きました:
写真と文章で詳しく解説! Javaメモリモデルとは何ですか

3.3. スレッド間の通信

2 つのスレッドがすべて動作する場合共有変数。共有変数の初期値は 1 です。各スレッドは変数を 1 ずつ増分します。共有変数の期待値は 3 です。 JMM 仕様には一連の操作があります。
写真と文章で詳しく解説! Javaメモリモデルとは何ですか
メイン メモリとローカル メモリ間の相互作用をより適切に制御するために、Java メモリ モデルでは、以下を実現するための 8 つの操作が定義されています。

  • ロック: ロックします。メイン メモリ内の変数に作用し、変数をスレッド専用としてマークします。
  • ロック解除: ロックを解除します。メインメモリ変数に作用してロックされた変数を解放し、解放された変数を他のスレッドでロックできるようにします。 ######読んで読んで。メイン メモリ変数に作用し、後続のロード アクションのためにメイン メモリからスレッドの作業メモリに変数値を転送します。ロードするには
  • load: を使用します。作業メモリ内の変数に作用し、読み取り操作によってメイン メモリから取得した変数値を作業メモリ内の変数のコピーに置きます。
  • 使用: 使用します。作業メモリに作用する変数は、作業メモリ内の変数値を実行エンジンに渡します。この操作は、仮想マシンが変数の値を必要とするバイトコード命令に遭遇するたびに実行されます。
  • assign: 割り当て。作業メモリ内の変数に作用し、実行エンジンから受け取った値を作業メモリ内の変数に割り当てます。この操作は、仮想マシンが変数に値を割り当てるバイトコード命令を検出するたびに実行されます。
  • ストア: ストレージ。作業メモリ内の変数に作用し、後続の書き込み操作のために作業メモリ内の変数の値をメインメモリに転送します。
  • 書く: 書く。メイン メモリ内の変数に作用し、ストア操作を作業メモリ内の変数の値からメイン メモリ内の変数に転送します。
注: 作業メモリはローカル メモリも意味します。

4. 考え方のまとめ

CPU とメイン メモリには桁違いの速度差があるため、マルチレベル キャッシュを備えた従来のハードウェア メモリ アーキテクチャを導入することを考えました。レベル キャッシュは CPU とメイン エンジンの間のバッファとして機能し、全体的なパフォーマンスを向上させます。これにより、速度の低下の問題は解決されますが、キャッシュの一貫性の問題も生じます。

データはキャッシュとメイン メモリの両方に存在します。標準化されていないと必ず災害が発生するため、従来のマシンではメモリ モデルが抽象化されています。

Java 言語は、メモリ モデルに基づいて JMM 仕様を発表しました。その目的は、マルチスレッドが共有メモリを介して通信する際のローカル メモリ データの不一致と、コンパイラによるコード命令の並べ替えと処理の問題を解決することです。プロセッサは、コードの順序どおりに実行されないなどの問題を引き起こします。

作業メモリとメインメモリ間の相互作用をより正確に制御するために、JMM では 8 つの操作 (

lock

unlockread) も定義しています。 、loaduseassignstorewrite推奨学習: 「

Java 学習チュートリアル

以上が写真と文章で詳しく解説! Javaメモリモデルとは何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcsdn.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。