Java仮想マシン-Javaメモリモデルのナレッジポイントの詳細な理解

なぜ並行性なのか?

  1. 非常に重要な理由は、コンピューターの計算速度とそのストレージおよび通信サブシステムとの間のギャップが大きすぎ、ディスクI / O、ネットワーク通信、またはデータベースアクセスに多くの時間が費やされていることです。また、コンピュータに同時に複数のタスクを処理させることは、プロセッサの計算能力を「絞る」非常に効果的な方法であると考え、証明する最も簡単な方法です。
  2. コンピュータプロセッサの機能を最大限に活用することに加えて、1つのサーバーが複数のクライアントに同時にサービスを提供するという、もう1つのより具体的な同時アプリケーションシナリオです。サービスのパフォーマンスを測定するには、1秒あたりのトランザクション数(Transactions Per Second、TPS)が最も重要な指標の1つです。これは、サーバーが1秒間に平均して応答できるリクエストの総数と、TPS値とプログラムの数を表します並行性には非常に密接な関係があります。

ハードウェアの効率と一貫性

ほとんどの計算タスクは、プロセッサの「計算」では完了できません。プロセッサは、操作データの読み取りや操作結果の保存など、少なくともメモリと対話する必要があります。このI \ O操作を排除することは困難です(すべての計算タスクを完了するためにレジスターに依存することはできません)

コンピュータのストレージデバイスとプロセッサの計算速度には数桁の差があるため、最近のコンピュータでは、プロセッサの計算速度にできるだけ近い位置で読み取りと書き込みを行うキャッシュ層(キャッシュ)を追加する必要があります。バッファ:操作が完了すると、キャッシュからメモリに同期されるため、プロセッサはメモリの読み書きが遅いのを待つ必要がありません。

キャッシュコヒーレンス:キャッシュコヒーレンスの問題を解決するために、各プロセッサは、キャッシュにアクセスするときにいくつかのプロトコルに従い、読み取りおよび書き込み時にプロトコルに従って動作する必要があります。このようなプロトコルには、MSI、MESI、MOSI、シナプスなどがあります。 。

アウトオブオーダー実行の最適化:プロセッサー内部のコンピューティングユニットを可能な限りフルにするために、プロセッサーは入力コードのアウトオブオーダー実行(Out-Of-Order Execution)を最適化する場合があり、プロセッサーは計算後に混乱します順次実行の結果は、結果が順次実行の結果と一致するように再編成されますが、プログラム内の各ステートメントの計算順序が入力コードの順序と一致することは保証されません。

Javaメモリモデル

メインメモリとワーキングメモリ

Javaメモリモデルでは、すべての変数がメインメモリに格納され、各スレッドには独自のワーキングメモリがあることが規定されています。ワーキングメモリは、スレッドで使用される変数のメインメモリコピーのコピーと、変数に対するすべての操作(読み取り、割り当てなど)はワーキングメモリで実行する必要があり、メインメモリの変数を直接読み書きすることはできません。異なるスレッドは、相手側のワーキングメモリ内の変数に直接アクセスできません。スレッド間での変数値の転送は、メインメモリを介して完了する必要があります。

下位レベルでは、メインメモリは物理ハードウェアのメモリに直接対応します。実行速度を向上させるために、仮想マシン(ハードウェアシステム自体の最適化対策も含む)は、ワーキングメモリを優先的にレジスタとキャッシュに格納できます。中、プログラムの実行中の読み取りおよび書き込みへの主なアクセスは作業メモリであるため。

メモリー間操作

メインメモリとワーキングメモリ間の特定の相互作用プロトコルに関して、完了するために以下の8つの操作がJavaメモリモデルで定義されています。仮想マシンの実装では、下記の各操作がアトミックで不可分であることを確認する必要があります。

  • ロック(lock):メインメモリに作用し、変数をスレッドの排他状態として識別します
  • アンロック
  • 読み取り(読み取り):後続のロードアクションのために、変数の値をメインメモリからスレッドの作業メモリに転送します
  • load:読み取り操作のメイン操作から取得した変数値を作業メモリの変数コピーに入れます
  • 使用:作業メモリ内の変数の値を実行エンジンに渡します。この操作は、仮想マシンが変数の値を必要とするバイトコード命令を検出するたびに実行されます
  • assign:実行エンジンから受け取った値を作業メモリの変数に割り当てます
  • ストア:ワーキングメモリー内の変数の値をメインメモリーに転送します
  • 書き込み:作業メモリーからストア操作によって取得された変数の値をメインメモリーの変数に書き込みます

:Javaメモリモデルには、順次操作が必要です:読み取り->ロード、保存->書き込み。ただし、順次実行のみが必要であり、連続実行が保証されるわけではありません。

揮発性変数の特別なルール

変数が揮発性として定義されている場合、変数には2つの特性があります。

すべてのスレッドに対してこの変数の可視性を確保します

ここでの「可視性」とは、スレッドがこの変数の値を変更すると、新しい値が他のスレッドにすぐに認識されることを意味します。

揮発性変数は可視性のみを保証できます。次の2つのルールを満たさない操作シナリオでは、ロックによって原子性を保証する必要があります(同期またはjava.util.concurrentの原子クラスを使用)。

  • 操作の結果は変数の現在の値に依存しないか、単一のスレッドのみが変数の値を変更することを保証できます
  • 変数は他の状態変数との定数制約に参加する必要はありません
命令の並べ替えの最適化を禁止する

通常の変数は、メソッドの実行中に割り当ての結果に依存するすべての場所で正しい結果が得られることを保証するだけですが、変数割り当て操作の順序がプログラムコード内の実行順序と同じであることは保証できません。

メモリバリア:https : //www.jianshu.com/p/64240319ed60

longおよびdouble変数の特別なルール

非原子的合意

Javaメモリモデルでは、ロック、ロック解除、読み取り、読み込み、読み込み、割り当て、使用、保存、および書き込みの8つの操作がすべてアトミックである必要がありますが、64ビットデータ型(longおよびdouble)の場合、比較的ルーズなものがモデルで明確に定義されます規制:揮発性によって変更されない64ビットデータの読み取り操作と書き込み操作を仮想マシンが2つの32ビット操作に分割できるようにします。つまり、仮想マシンが読み込み、保存、読み取り、および64ビットデータタイプの選択を実現できるようにします。これら4つの操作の原子性を記述します。

先制原則

事前発生は、Javaメモリモデルで定義された2つのオペレーション間の部分的な順序関係です。オペレーションAがオペレーションBの前に発生する場合、オペレーションBが発生する前に、オペレーションBによってオペレーションAの影響を観察できます。 「影響」には、メモリ内の共有変数の値の変更、メッセージの送信、メソッドの呼び出しが含まれます。

Javaメモリモデルでの「自然な」既存の関係
  • プログラム順序規則:スレッド内で、プログラムはコードに従ってフロー順序を制御します
  • ロック規則の監視:ロック解除操作は、同じロックでのロック操作の前に発生します。
  • スレッド開始ルール
  • 揮発性変数の規則揮発性変数への書き込み操作は、この変数への読み取り操作の後に最初に発生します
  • スレッド終了規則
  • スレッド中断規則(スレッド中断規則):スレッド中断()メソッドの呼び出しは、中断されたスレッドのコードが中断イベントの発生を検出する前に発生し、中断が発生したかどうかはThread.interrupted()メソッドで検出できます
  • オブジェクトのファイナライズルール(ファイナライザールール):オブジェクトの初期化(コンストラクターの実行の終了)は、最初にfinalize()メソッドの開始時に行われます
  • 推移性:オペレーションAがオペレーションBの前に発生し、オペレーションBがオペレーションCの前に発生する場合、オペレーションAがオペレーションCの前に発生したと結論付けることができます。

Javaとスレッド

スレッドの実装
  • カーネルスレッドを使用する
  • ユーザースレッドを使用
  • ユーザースレッドと軽量プロセスの混合使用
Javaスレッドの実装

SunJDKの場合、彼のWindowsバージョンとLinuxバージョンは1対1のスレッドモデルを使用して実装され、Javaスレッドは軽量プロセスにマップされます。

Javaスレッドのスケジューリング

スレッドスケジューリングプロセスは、二つの主要なスケジューリング、すなわちあるプロセッサ・システムの使用権に割り当てられたスレッドを指す協調スレッドスケジューリング(協調型スレッドスケジューリング)プリエンプティブスレッドスケジューリング(プリエンプティブスレッドスケジューリング)

協調スレッドスケジューリング

協調スケジューリングマルチスレッドシステムを使用する場合、スレッドの実行時間はスレッド自体によって制御されます。スレッドが処理を終了した後、スレッドはシステムに通知して、別のスレッドに切り替える必要があります。

利点:実装が簡単で、スレッドは自身の作業を終了した後にスレッドを切り替えるため、切り替え操作はスレッド自体に知られているため、スレッド同期の問題はありません。

短所:スレッドの実行時間を制御できない

プリエンプティブスレッドスケジューリング

プリエンプティブスケジューリングのマルチスレッドシステムが使用されている場合、各スレッドにはシステムによって実行時間が割り当てられ、スレッドの切り替えはスレッド自体によって決定されません。

オリジナルの記事を8件公開 Like1 訪問数262

おすすめ

転載: blog.csdn.net/qq_40635011/article/details/105429062