1. JAVA並行性モデル共有メモリモデル共有メモリ同時実行モデルでは、スレッドはプログラムの共通状態を共有し、スレッドはメモリ内の共通状態を読み書きすることで暗黙的に通信します。 このメモリはメインメモリを指しますが、実際には物理メモリの小さな部分です。 2. JAVAメモリモデルの抽象化1. Javaメモリ内のどのデータがスレッドセーフで、どのデータが安全でないのかスレッドセーフではありません: Java では、すべてのインスタンス フィールド、静的フィールド、配列要素がヒープ メモリに格納され、これらのデータはスレッドによって共有されるため、メモリの可視性の問題が発生します。 スレッドセーフティ ローカル変数、メソッド定義パラメーター、および例外ハンドラー パラメーターは、現在のスレッドの仮想マシン スタック内のデータであり、スレッド間で共有されないため、メモリの可視性の問題は発生しません。 2. スレッド間通信の性質スレッド間通信の本質は JMM (JAVA メモリ モデル) がこのプロセスを制御します。 JMM は、スレッドの共有変数への書き込みが他のスレッドに表示されるタイミングを決定します。 上の図から、スレッド間の通信はメインメモリを介して行われ、メッセージが送信されることがわかります。各スレッドが共有データを処理する場合、共有データを現在のスレッドのローカル メモリ (各スレッドには独自のメモリがあります) にコピーして操作します。 メッセージ通信プロセス(データセキュリティの問題を考慮せずに)スレッド 1 は、共有変数 A をメイン メモリから自身のローカル メモリにロードして処理します。たとえば、A = 1;このとき、変更された共有変数 A はメインメモリにフラッシュされ、スレッド 2 はメインメモリ内の共有変数 A をローカルメモリに読み込んで操作します。データ相互作用プロセス全体はJMMによって制御され、主にメインメモリが各スレッドのローカルメモリとどのように相互作用するかを制御して共有データの可視性を提供します。 3. 並べ替えプログラムが実行されると、効率を向上させるためにプログラム命令が並べ替えられます。 1. カテゴリの再並べ替えコンパイラ最適化の並べ替え コンパイラは、シングルスレッド プログラムのセマンティクスを変更せずに、ステートメントの実行順序を最適化します。 命令セットの並列並べ替え データ依存関係がない場合、プロセッサはステートメントの実行順序を変更できます。 メモリシステムの並べ替え プロセッサはキャッシュと読み取り/書き込みバッファを使用するため、ロード操作とストア操作が順序どおりに実行されないように見える場合があります。 2. 再注文プロセス上記の 3 つの並べ替えにより、並行プログラムを作成するときにメモリの可視性の問題が発生します。 JMM のコンパイラ並べ替えルールでは、特定の種類のコンパイラ並べ替えが禁止されています。 JMM のプロセッサ並べ替えルールでは、Java コンパイラが命令シーケンスを生成するときに特定のメモリ バリア命令を挿入し、メモリ バリア命令を使用して特定のタイプのプロセッサの並べ替えを禁止する必要があります。 3. プロセッサの並べ替えプロセッサがメモリにデータを書き込むのを待つ遅延を回避するために、プロセッサとメモリの間にバッファが追加され、プロセッサはバッファにデータを書き込み続け、一定時間後にバッファ内のデータを一度にメモリにフラッシュできるようになります。 アドバンテージ: 1. プロセッサの一時停止方法が変更され、プロセッサの動作効率が向上します。 2. メモリにデータを書き込む際のメモリバス使用量を削減する 欠点: 各プロセッサの書き込みバッファは現在のプロセッサにのみ表示されるため、次のシナリオのように、メモリ操作の実行順序は実際の状況と一致しません。 現在のシナリオでは、プロセッサ A とプロセッサ B がそれぞれの書き込みバッファ内のデータをメモリにフラッシュせず、メモリから読み取った A=0 と B=0 を X と Y に割り当てる可能性があります。この時点で、バッファ内のデータがメモリにフラッシュされ、最終結果が実際の目的の結果と一致しなくなります。バッファ内のデータがメモリにフラッシュされたときにのみ、実際の実行と呼べるからです。 メインメモリとワーキングメモリ間の特定の相互作用プロトコル、つまり変数がメインメモリからワーキングメモリにコピーされる方法と、ワーキングメモリからメインメモリに同期される方法は、JMM によって詳細に実装されており、次の 8 つの操作が定義されています。 メインメモリから作業メモリに変数をコピーする場合は、読み取り操作とロード操作を順番に実行する必要があります。変数を作業メモリからメインメモリに同期する場合は、保存操作と書き込み操作を順番に実行する必要があります。ただし、Java メモリ モデルでは、上記の操作を順番に実行する必要があることのみが要求され、連続して実行する必要があることは保証されません。 操作実行フロー図: 同期ルール分析
4. メモリバリア命令プロセッサの並べ替えによって発生するメモリ エラーを解決するために、Java コンパイラは、生成された命令シーケンス内の適切な場所にメモリ バリア命令を挿入し、特定の種類のプロセッサの並べ替えを禁止します。 メモリバリア命令 5. 事前に起こること事前発生原則は、プログラム実行の原子性、可視性、および順序を保証するのに役立ちます。これは、データの競合があるかどうか、およびスレッドが安全かどうかを判断するための基礎となります。 JMM では、ある操作の結果を別の操作から参照できるようにする必要がある場合、2 つの操作の間に事前発生関係が存在する必要があります (2 つの操作は同じスレッド内にある場合もそうでない場合もあります)。 ルールの内容: プログラム順序ルール分岐、ループなど、スレッド内のコードシーケンスを制御することを指します。つまり、スレッド内では意味的なシリアル性が保証され、コードの順序どおりに実行される必要があります。 ロックルールロック操作の前にロック解除操作を実行する必要があります。つまり、ロックがロック解除されてからロックされた場合、ロック解除操作の後にロック操作を実行する必要があります (同じロックに対して)。 揮発性変数のルール揮発性変数への書き込み操作は、この変数の読み取り操作の前に実行される必要があり、これにより揮発性変数の可視性が保証されます。簡単に言えば、スレッドが揮発性変数にアクセスするたびに、メイン メモリから変数の値が強制的に読み取られ、変数が変更されると、最新の値がメイン メモリに強制的に更新されます。いつでも、異なるスレッドが変数の最新の値を見ることができます。 スレッド開始ルール スレッド開始メソッドstart()は、現在のスレッドのすべての操作の前に実行する必要があります。 スレッド終了ルール スレッド内のすべての操作は、スレッドが終了する前に実行する必要があります。 Thread.join() メソッドの機能は、現在実行中のスレッドが終了するまで待機することです。スレッド B が終了する前に共有変数が変更されたと仮定します。スレッド A がスレッド B の join メソッドから正常に戻ると、スレッド B による共有変数の変更がスレッド A に見えるようになります。 スレッド中断ルール 中断されたスレッドのコードが割り込みイベントを検出する前に、スレッドは interrupt() メソッドを呼び出します。 オブジェクトの終了ルール オブジェクトをリサイクルする前にオブジェクトの初期化を完了する必要があります 推移規則 操作 A が操作 B の前に発生し、操作 B が操作 C の前に発生する場合、操作 A は操作 C の前に発生する必要があります。 注: 2 つの操作の間に事前発生関係が存在するということは、前の操作を次の操作の前に実行する必要があることを意味するものではありません。必要なのは、前の操作の結果が次の操作に表示され、前の操作が次の操作の前に順序付けられていることだけです。 6. データの依存性前の操作の結果は次の操作の結果に影響します。このとき、コンパイラとプロセッサは、データ依存性のある現在の操作を処理するときに、データ依存性のある 2 つの操作の実行順序を変更しません。 注: ここで説明するデータ依存関係は、単一のプロセッサで実行される命令シーケンスまたは単一のスレッドで実行される操作にのみ適用されます。コンパイラとプロセッサは、異なるプロセッサや異なるスレッドの状況を考慮していません。 7. あたかもシリアルのようにシングルスレッドの場合、どのように順序を変更してもプログラムの実行結果は変わりません。したがって、単一のプロセッサまたは単一のスレッドの場合、コンパイラとプロセッサはデータ依存性のある操作を並べ替えません。逆に、操作にデータ依存性がない場合、命令の並べ替えが発生する可能性があります。 4. データの競合と順序の一貫性データの競合はマルチスレッドの状況でのみ発生します 1. データ競争変数は 1 つのスレッドで書き込まれ、別のスレッドで読み取られますが、書き込みと読み取りは同期されていません。 2. 順序一貫性プログラムがマルチスレッド条件下で同期メカニズムを正しく使用できる場合、プログラムの実行は順次一貫性を保ち (シングルスレッド条件下で実行された場合と同様)、プログラム実行の最終結果は期待どおりのものになります。 3. シーケンシャル一貫性メモリモデル5.3.1 機能: スレッド内のすべての操作は、プログラムの順序に従って実行する必要があります。すべての操作はアトミックであり、他のスレッドから見える必要があります。 5.3.2 コンセプト: 概念的には、シーケンシャル一貫性には単一のグローバル メモリがあり、どの時点でも最大 1 つのスレッドがそのメモリに接続できます。マルチスレッド シナリオでは、すべてのメモリ読み取りおよび書き込み操作がシリアル化されます。 5.3.3 例: たとえば、複数の同時スレッド ABC があり、スレッド A には 2 つの操作 A1 A2 があり、その実行順序は A1->A2 です。スレッド B には 3 つの操作 B1、B2、B3 があり、その実行順序は B1->B2->B3 です。 C スレッドには 2 つの操作 C1 C2 があるため、プログラム内で実行される順序は C1->C2 になります。 シナリオ分析: シナリオ 1: 同時実行セーフ (同期) 実行順序 A1->A2->B1->B2->B3->C1->C2 シナリオ 2: 同時実行が安全でない (非同期) 実行順序 A1->B1->A2->C1->B2->B3->C2 結論は: 非同期シナリオでは、3 つのスレッドがそれぞれ順序どおりに実行されなくても、各スレッド内のそれぞれの操作は順序どおりに実行されます。また、すべてのスレッドは、一貫した全体的な実行順序のみを参照できます。つまり、3 つのスレッドすべてが次の順序を参照します: A1->B1->A2->C1->B2->B3->C2。これは、シーケンシャル一貫性メモリ モデル内のすべての操作が、どのスレッドにもすぐに表示される必要があるためです。 上記のケースのシナリオは JMM には当てはまりません。 JMM では、非同期プログラムの全体的な実行順序が変わるだけでなく、各スレッドから見た操作実行順序も異なります。 例えば、前述のように、スレッド A が変数 a=2 の値を自身のローカルメモリに書き込み、まだメインメモリにフラッシュしていない場合、スレッド A は値が変更されたことを認識しますが、他のスレッド B と C はまったく変更を認識しないため、スレッド A の操作は発生していないと認識します。スレッド A が作業メモリの値をメインメモリにフラッシュバックした場合にのみ、スレッド B と C はそれを参照できます。ただし、同期の場合、順次一貫性モデルと JMM モデルの実行結果は一致しますが、プログラムの実行順序は必ずしも同じではありません。JMM では命令の並べ替えが発生するため、実行順序が不一致になります。 |
<<: JVM の詳細な分析: JVM はリフレクションをどのように実装しますか?
>>: JD Retail Cloud mPaaS が先導し、銀行業界のデジタル変革とアップグレードを支援します。
dedispec.comは2009年に設立されました。主に独立サーバーのレンタルとホスティングを行っ...
インターネットのビジネスモデルには 3 つのレベルがあります。最下層は製品中心、次がプラットフォーム...
中国江蘇ネットは5月12日、大ヒット作の公開後、映画館で映画を観るのが嫌いなファンにとっては、オンラ...
今日では、企業はデータベースなしではクラウドに移行できません。ただし、クラウド上にはさまざまな種類の...
この記事の著者は曹正(4399 建築家)です。この記事は曹正の百度空間 Caoz の和音ブログから引...
まず私の状況についてお話しします。資格は低いが諦めなかった私はさまざまな理由で高校を中退し、その後、...
インターネット コンテンツの更新プロセスでは、企業の Web サイトのスナップショットの更新を確実に...
百度のGreen Radishアルゴリズムの導入に続いて、Googleは公式ブログで再度警告した。リ...
2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っています4年に一度...
Racknerd は 2 月末に、トラフィックの多い 3 つの VPS のプロモーションを開始しまし...
から運営されている Host4fun は、インド企業である QuadSpark IT Solutio...
[51CTO.com からのオリジナル記事] Infrastructure as a Service...
新浪テクノロジー 張南中国最大の高画質海賊版ポータルサイトが警察によって閉鎖され、国内の多数の海賊版...
Vultr は誰もがよく知っています。世界中の 15 のデータセンター (日本 VPS、シンガポール...
インターネットに注目している友人は、最近、Google のランキング アルゴリズムの考え方が変わり、...