X. [ベーシック]同時Javaのメモリモデルの基本

1.基本概念

1.1プログラム

それは可能なコンピュータプログラムのセットで識別して実行する特定の人々のニーズ満たすために、コンピュータの実行方法を情報技術ツールを

1.2プロセス

設計プロセスの初期段階のためのコンピュータ・アーキテクチャでは、基本的なプロセスは、プログラムの実体の実行で、スレッドのための現代のコンピュータアーキテクチャの設計では、プロセスは、コンテナのスレッドです

1.3スレッド

オペレーティングシステムは、スケジューリングの最小単位を算出することができます。ほとんどの場合、それは、プロセスの単位プロセスの実際の動作が含まれます。スレッドは、プロセスシーケンスの単一の制御フローを参照して、プロセスは、並行して、各スレッドは、異なるタスクを実行するために、複数のスレッドによって複雑にすることができます。

2. JVMのスレッド

2.1 JVM

本物行うには、マシンのスタック構造に仮想マシンのバイトコードのJavaを実行することができます(JVMと略記Java仮想マシン、英語)、Java仮想マシン。Java仮想マシンは、独自のサウンド有するハードウェアアーキテクチャを、対応する命令を有する、等のプロセッサ、スタック、レジスタなど、。JVMは、Javaプログラムが複数のプラットフォーム上で変更せずに実行することができるJava仮想マシンで実行中のオブジェクトコード(バイトコード)を生成するように、特定のオペレーティング・システム・プラットフォームに関連する情報をマスク。JVMは、プログラミング言語の仮想マシンとして、実際には、唯一の任意の言語でJVMでコンパイルして実行することができ、コンパイルされたファイル形式をロードするためにJVMの要件に結果としてコンパイルされたファイルが準拠する限り、Java言語に特化されていません。

JVMの実行

JVMは、コンパイルされたプログラムで、停止は、プログラムの最後に実行されている、公式の開始後に走り出しました。ここでは、JVMは、1つまたは複数のスレッドが含まれているプロセスです。

3. JVMのメモリ領域

JVMのメモリ領域

3.1ヒープ

特に中にJavaオブジェクトを格納するための「スタック」のJVM(ヒープ)メモリ領域この定義によると、Javaのヒープ上のすべてのオブジェクト、およびスタックは基本タイプとオブジェクト参照が格納されていないので、唯一のオブジェクト自体を格納します。のみすべてのスレッドで共有される単一のJVMのヒープは、管理自動メモリ管理メカニズムのいくつかの種類によって、オブジェクトクラスは、このようなメカニズムは、多くの場合、「ガベージコレクション」またはGC(ガベージコレクション)と呼ばれています。そこにヒープメモリの割り当てには完全な例ではありません、そしてスタックはもはや広げることができれば、それはOutOfMemoryErrorが発生がスローされます

3.2メソッドゾーン

各スレッドは、店舗クラス情報を仮想マシンにロードされているために使用される共有メモリ領域は、あるとして地区方法(方法エリア)とJavaヒープは、定数は、静的変数は、タイムコンパイラは、コードおよび他のデータをコンパイルします。Java仮想マシンの仕様では、メモリ割り当て領域の方法は、需要を満たすことができない場合、OutOfMemoryErrorが発生をスローします

3.3 VMスタック、スタック領域

特に、基本データ型と自己保存の方法の基準(ないオブジェクト)が定義されたオブジェクトのための「スタック」(スタック)でJVM メモリ領域各スレッドは、スレッドが作成されたときに作成したスタック領域、スタック領域が含まれ、そのライフサイクルは生命の糸、スレッドの終了時に解放スタック領域に従うことです。データ(プリミティブ型およびオブジェクト参照)プライベートで、他の人がアクセスは、各スタックをスタックすることはできません。基本的な変数の型、および実行環境のコンテキスト、操作指示領域(ストレージ操作命令):スタックは、3つの部分に分かれています。Java仮想マシン仕様では、この領域が提供して異常の2種類を:スタックは、スレッドの深さは、仮想マシンの許容深さを要求されたよりも大きい場合、StackOverflowError例外をスローします。仮想マシンを動的にスタックを展開することができるかどうか(現在のJavaのほとんど、)仮想マシンを動的に拡張することができますが、Java仮想マシン仕様では、仮想マシン・スタック、固定長を可能にする拡張が十分なメモリを適用することができない場合に例外をOutOfMemoryErrorがスローされます

3.4ネイティブメソッドスタック、ネイティブメソッドスタック

ネイティブメソッドスタックと(つまり、バイトコード)仮想マシンが果たした役割は非常に似ていますが、違いはJava仮想マシンのメソッドのための仮想マシンの実行スタックでスタックサービス、およびローカルスタック方法は、仮想マシンを使用することですサービスのネイティブ方法。

パーソナルコンピュータ

ここでPCは、通常のコンピュータを参照しますが、プログラム・カウンタ(プログラム・カウンタ・レジスタ)ショートしない、それは小さなメモリ空間で、その役割は、現在実行中のスレッドのインジケータバイトコードの行番号として見ることができます。職場でのバイトコードインタプリタを実行するカウンタの値を変更することによって選択される場合、仮想マシンのの概念モデルでは、(唯一の概念モデル、仮想マシンの様々ないくつかのより効率的な方法を達成通じ行くかもしれません)バイトコード命令、分岐ループ、分岐、例外処理、およびその他の基本的な機能のスレッドの回復は完全にカウンターに依存しています。

4. Javaのメモリモデル(JMM)

4.1 JMM

(:JVMと略記Javaのメモリモデル、英語)、合意に達することができる様々なプラットフォームでJavaプログラムを聞かせて達成するために、メモリアクセス時のシステムの違いをさまざまなハードウェアをオフに遮断し、操作するための仮想マシン仕様の一種Javaのメモリモデル同時効果。JMMのJava仮想マシンの仕様とコンピュータメモリがどのように連携して動作することです:スレッドが指定する際に、どのように共有変数を同期させる必要があるときは、あなたが他のスレッドによって変更共有変数の値の後、どのようにアクセスを見ることができます。

JNN

4.2メインメモリ

また、共有メモリとして知られている、Javaのメモリモデルは、すべての変数がメインメモリに存在している必要があり。

4.3ワーキングメモリ

また、プライベートメモリとして知られ、各スレッドは、ワーキングメモリで行われるべき変数の操作をスレッディング、独自のワーキングメモリを持っている、あなたは直接、異なるスレッド間の他の変数のワーキングメモリにアクセスすることはできません。

メインメモリのワーキングメモリと4.4の関係

メモリに記憶された各変数の定義されたJavaメモリ・モデル・プログラム・アクセスルールの主な目的、すなわち、そのような変数の基礎となる詳細は、仮想マシンの変数にメモリから削除されます。

Javaプログラミング変数で述べた変数が異なる場合、それは、対象となるインスタンスフィールド、静的フィールドと配列要素を、しかし含まないローカル変数とメソッドのパラメータを、後者はスレッドにプライベートであるため、したがって、当然何の競争が存在しない、共有されることはありません。

各スレッドは、(など読んで、割り当て、)変数のすべての操作をスレッド、コピーのメインメモリコピーに保存されたワーキングメモリのスレッドがスレッド変数を使用することで、独自のワーキングメモリを持つワーキングメモリ内になければなりませんしかし、直接ではなく、メインメモリ変数を読み書きします。異なるスレッド間で直接、スレッド間を通過する価値がある他の変数のワーキングメモリにアクセスすることはできませんメインメモリによって行われる必要があります。

4.5作業のメカニズム

  1. プライベートデータを変更します

スレッドが直接彼らのワーキングメモリ変数を変更します

  1. 変更は、データを共有しました

最初のデータは、ワーキングメモリ内の修正後、データをメインメモリにフラッシュされ、ワー​​キングメモリにメインメモリからコピーされ、変更されます

メモリの間の相互作用4.6

メインメモリとワーキングメモリスワップ協定の間のコンクリートについて、つまりどのように作業メモリにメインメモリから変数のコピー、メインメモリに戻って同期する方法の実装の詳細とワーキングメモリからのように、Javaのメモリモデルの定義操作のどのような8種類完了し、各操作原子は、以下の通りであるときに、仮想マシンの実装分割することができないことを保証しなければなりません。

オペレーティング 定義 コンセプト
ロック ロッキング スレッド排他状態変数として識別されるメインメモリ変数に作用します
ロック解除 ロック解除 そして、変数がロック状態での変数の解放後、解放されていることをメインメモリ変数の役割は、他のスレッドをロックすることができます
読む 読みます その後の使用のロード操作のため、メインメモリ上の変数作用する、スレッドの作業メモリにメインメモリから送信された変数の値が、
負荷 積載 変数に取得されるワーキングメモリ上の変数の演技は、ワーキングメモリに変数値のメインメモリコピーから読み取ります
つかいます 使用 ワーキングメモリの変数に適用した場合、この操作は、仮想遭遇バイトコード命令は、変数の値を使用する必要があるときはいつでも、それは、可変エンジンを実行するためにメモリの値を渡し、実行されます
割り当てます 割り当て 変数ワーキングメモリに割り当てられた値に実行エンジンから受信されたワーキングメモリ、上の変数演技、この操作を実行するための変数割り当ての機会があることでしょうたびに仮想バイトコード命令
格納 メモリ 変数の値を使用して、次の書き込み動作のために、メインメモリに転送された可変ワーキングメモリに作用する、ワーキングメモリ
書きます 書き込み のメインメモリにワーキングメモリの動作に由来する変数の値を格納するメインメモリに作用する変数変数

ここで、負荷を読んで、店の書き込みが連続して実行する必要がありますが、連続して行われることが保証されていません。これらの定義は非常に厳しいですが、非常に面倒な、我々は等価性判断の原則を持っているので、多くの問題を練習-------原理は、並行環境で安全にするかどうかのアクセスを決定するために、最初に発生します。

5.並行プログラミング

5.1同時実行

期間は、複数のプログラムを開始した時間を指すが、プロセッサ上で実行されている時間内に完成し、これらのプログラムは、同じプロセッサ上で実行されているが、任意の一点の間で実行するために実行している1つのプログラムだけです。

5.2スレッドセーフ

プログラム内の共有データが複数のスレッドを並列に実行され、同期メカニズムによってスレッドセーフなコードは、各スレッドが適切かつ正確に実行できることを保証するために、全く驚きデータ汚染がありません。

5.3シーン

そこラッシュチケットシステムは、誰もが家に休日に行きたかった、今あるが、唯一の非常に多くのチケットなので、C、Bのチケットが2を購入、4枚のチケットの合計を想定し、午前中にチケットを購入する多くの人々をチケット10の販売を開始しますサーバが同時に2つの要求を受信したため4枚のチケットを購入、彼はただのデータは、今BBは、ハンドルにCCが同時にメインメモリから取得二つのスレッドBとCを要求する二つのスレッドを作成し、サーバーに同時に提出しました次いで、データは、4枚のチケットを残し、2つのスレッド、BBは、2つのスレッドが完売チケットをみなすようにB、Cのニーズを満たすために考えCCのニーズを満たすと考えられ、6つの結果を完売、およびB Cチケットは間違いなく繰り返しである、これは実際のビジネスニーズに沿ったものではありません。

ここで、B、グラブに同時にCはグラブにグラブに登場し、残りの4枚のチケットが6票、我々はスレッドセーフであると信じるこの場合のうち投票しながら、この概念は、並行処理と呼ばれる投票します。

5.4同時JMMしてコンパイル

Javaのメモリモデルは、原子の同時プロセス、可視性と秩序を処理する方法でこれらの三つの特徴を周りに構築することです。

5.4.1三つの特徴

  1. 不可分性
    1. 直接Javaのメモリモデルによるアトミック操作変数を読み込み、負荷、割り当て、使用、保存、書き込みなどが保証し、我々は一般的に、基本的なデータ型は読んだことがあると書き込みアクセスがアトミックであると考えることができます。
  2. 可視
    1. 可視性は、スレッドが共有変数の値を変更したときに、他のスレッドはすぐにこの変更を認識することができます。
  3. 整頓
    1. あなたはこのスレッドで観察する場合は、「スレッドのシリアルセマンティクス内のパフォーマンスは」、そう、すべての操作が順序付けられているからです。
    2. スレッド内の他のスレッドは、すべての操作が乱れている場合、「命令並べ替え」現象と「ワーキングメモリとメインメモリの同期遅延」現象ので、観察されました。

5.4.2原則は、最初に発生しました

最初の発生の原理は、競合が存在するデータは、スレッドセーフかどうか、それは実際には、最初の操作が操作Bで発生した場合、Java(登録商標)メモリ・モデルで定義された2つの操作の間の半順序関係を指すかどうか、判断するための主な基礎であるのそれ手順Bの発生の前に、それが産生され、Bが観察された操作の操作に影響を与えることができます。

ここではいくつかの「自然」の関係は、最初にどのような援助同期のない関係が存在しているJavaのメモリモデル、これらの事前の下で起こっています。

  1. プログラムシーケンス規則:スレッドで、コードブックEDITORIAL書き込み動作のプログラム順序によると、最初の操作後に発生します。
  2. 管理ブロックルール:最初の発生時にロック付きフェイスアンロック操作ロック操作。これは、同じロックで、「バック」は、時間内の順序を指し、ここで強調しておかなければなりません。
  3. 揮発性変数のルール:volatile変数への書き込み操作は、この変数の顔に先読みが発生しました。「戻る」の時間に順番を指します。
  4. スレッド開始ルール:このスレッド毎動きの開始スレッドオブジェクト()メソッドが最初に出現しました。
  5. スレッドには、ルールを終了します。すべての操作は先にスレッドの終了のです。このスレッドの検出に起こります。
  6. スレッドには、ルールを破る:移送ライン()メソッド割り込み優先度のスレッドが発生する割り込みイベントに割り込まれたスレッドコード検出で行われます。
  7. ルールオブジェクトの終了:オブジェクトの初期化は、最初に起動し、そのファイナライズ()メソッドで発生した(コンストラクタ実行終了)を完成します。
  8. 推移は:最初の操作が操作Bに発生した場合、B最初の操作が操作Cで発生した、操作が結論そのAさんCさんの運転で発生したと判断することができます。

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

スレッドスケジューリングプロセスは、主に二つの方法、すなわち共同スケジューリングとプリエンプティブなスケジューリングをスケジューリング、割り当てられているプロセッサスレッドを使用する権利のためのシステムをいいます。

6.1共同スケジューリング

協調マルチスレッドシステムをスケジュールした場合、スレッドの実行時間は、スレッド自体によって制御され、積極的にシステムに通知するために、彼らの仕事を行った後、スレッドが別のスレッドに切り替えます。

コラボレーティブなスケジューリングの最大の利点は、簡単で、スレッドは、独自の事務を切り替えるスレッド前に終了しなければならないので、自分のスレッドの切り替え操作が知られているので、どのスレッドの同期の問題はありません。

同時に、その欠点がある:スレッドの実行時間は、スレッドを書くことに問題があっても、制御することができず、スレッドはシステムを切り替えて語られていない、プログラムがブロックされていたであろう。

6.2プリエンプティブスケジューリング

あなたはプリエンプティブスケジューリングマルチスレッドシステムを使用する場合は、システムは、各スレッドの実行時間を割り当てます、スレッド切り替えスレッド自体が(Javaの、Thread.yield()の実行時間を可能に)決めるのに役立ちます。この実装モードスレッドスケジューリングでは、スレッドの実行時間は、制御システムは、ブロックされたスレッドをもたらす問題全体のプロセスが存在しないであろう、スレッドスケジューリングは、Javaプリエンプティブ・スケジューリングを使用することです。このようなWindowsの、問題があるプロセスとして、我々は、プロセスを移動するには、タスクマネージャを使用することができ、「殺します。」

Javaのスレッドのスケジューリングシステムは自動的に行わが、我々はまた、いくつかのスレッドの実行時間よりも多くの少しを割り当てるためのシステムを「推奨」することができますしますが、他のスレッドが少なく少しで割り当てることができ-----この操作は、スレッドによって設定することができます優先順位が完了します。

レディ状態にあるときに、2つのスレッドは、優先度の高いラインチェンYuerongを容易にシステム選択を実行します。

しかし、Javaスレッドを達成するためにシステムアップを通じてネイティブスレッドにマッピングされているので、ホームゲームをねじ込みも、あまりにもトリッキーではないので、スレッドのスケジューリングは、最終的には、オペレーティング・システムに依存し、「優先プロペラ」になるために、Windowsのシステムがあります関数は、その役割は、システムが、実行のスレッドは、特に「ハードワーク」であったと認めるときは、それの実行時間を割り当てるようにスレッドの優先度を超えてもよい略です。

7.スレッド状態

Java言語が時間内にいずれかの時点で、5つのスレッドの状態を定義し、1つのスレッドのみ、唯一の状態にそれらを持っています。

7.1新(新)

あなたはまだこの状態で開始されていないスレッドを作成した後。

7.2実行(Runable)

、状態のスレッドの時間はおそらく実行されているオペレーティングシステムのスレッド状態の実行と準備を含め、それに割り当てられたCPU実行時間のためにそこに待っていてもよいです。

無期限7.3待ち(待機)

スレッドはCPU実行時間が割り当てられることはありません、彼らは他のスレッドを待つしたいディスプレイをウェイクアップされ、次のような方法は、無期限の待機状態にスレッドします。

  1. タイムアウトパラメータははObject.wait()メソッドで設定されていません。
  2. Timeoutパラメータは、Thread.join()メソッドを設定されていません。
  3. LockSupport.park()メソッド

7.4そこ期間を待っている(時限待機)

スレッドは、CPUの実行時間を割り当てることができないが、他のスレッドが表示されたウェイクを待たずに、彼らは一定時間後にシステムが自動的に起動します。以下の方法では、待機状態にスレッドの期限を持っています。

  1. Thread.sleep()メソッド
  2. Object.waitセット()メソッドのタイムアウトパラメータ。
  3. Thread.joinセット()メソッドのタイムアウトパラメータ。
  4. LockSupport.parkNanos()
  5. LockSupport.parkUnitl()

7.5遮断(ブロック)

され、「待ち状態」、ブロックされた状態が排他ロックを取得するのを待って、この時間は、ロック時間をあきらめて別のスレッドで行われます:スレッドがブロックされた、「ブロック」と「待ち状態」の区別があります一定の時間を待っている、またはウェイクアクションは、同期プログラム領域に入るのを待っている間、スレッドがこの状態になります、行われます。

7.6終了

終了したスレッドの状態。

おすすめ

転載: juejin.im/post/5dd7e16af265da7e26473667