Javaの並行処理の概要:安全なマルチスレッド

1.同時基礎

定義:複数のタスクと複数のスレッドを処理するために、「同時に」CPUは、このCPUリソースのために競合しています

1.1利点

マルチコアCPUの完全なコンピューティングパワー

アプリケーションのパフォーマンスを向上させ、業務を円滑スプリット

1.2の欠点

頻繁にコンテキストスイッチング時間がかかります

スレッド安全性の問題:アトミック、順序、並べ替え

1.3関連概念

同期、非同期:各メソッドを実行するために呼び出し元のコードのバックの終了後に呼び出されているかどうかであります

同時、平行:前者は処理タスクの「同時」複数を切り替えることにより、CPUのタイムスライスを指し、後者は、真の意味にCPUを複数指します

ブロッキング、ノンブロッキング:スレッドが重要なリソースを保持している場合は、他のスレッドは、スレッドを待ち、その後、実行を継続するために、リソースの解放を待つ必要が中断され、それが障害物であり、非ブロックコントラスト、誰のスレッドが他のスレッドをブロックすることはできないことを強調すべてのスレッドが前方に実行しようとします

クリティカルセクションは:スレッドが占有する場合、他のスレッドが待機する必要があり、1は共通のリソースやデータを共有する複数のスレッドで使用することができ表し

2.スレッドの基本

2.1スレッドの方法を作成

継承スレッド、再runメソッド(制限:単一継承のみ)

Runable、渡されたスレッドを達成

呼び出し可能な達成、スレッドプールに提出

2.2スレッドの状態

17130423-54522b8ba69c3195.png!ウェブ

国家javaの同時実行スレッド.PNG _

NEW知人状態が作成されますが起動しない()されます

RUNNABLE動作状態(実際にはシステムの場合のスケジューリングおよびREADY状態RUNNINGに分割することができます)

ロックするBLOCKEDブロックされ、スレッドブロック

他のスレッドや、中断の通知を待って、待っている過渡待ち

TIMED_WAITING待機タイムアウト、待機時間に達すると、スレッドは状態Runableに切り替わりますタイムアウト

TERMINATED終了状態、スレッドが終了します

2.3基本操作のスレッドの状態

2.3.1ストップ

暴力を停止し、それが放棄されています

2.3.2割り込み/ isInterruptedを/割り込ま

割り込み:(、スレッドオブジェクトを割り込みスレッドが()/(ロング)待つ/スリープ()/スリープ(ロング)待ち時間を呼び出す場合/(参加)/参加するとき(長い)メソッド例外:InterruptedExceptionをスローし、フラグをクリアスレッド中断は、実行中のスレッドが他のスレッドによって中断されているか否かを示すフラグとして理解することができます)

isInterruptedをこのスレッドが中断された場合、フラグはクリアされません。

中断:このスレッドが中断された場合、フラグがクリアされます

2.3.3参加

唯一それがブロックされているそれ以外の場合は、続行するために実行するプロセスに参加するのを待つの後に現在のスレッド

2.3.4スリープ

CPUのタイムスライスは、ロックを解除しません、あなたはどこにでも呼び出すことができるように睡眠は、次のリソースを取得するために待機するスレッドプールの端部に、睡眠時間を静的メソッドスレッド

2.3.5待機

待機を待った後、プールを出た後、インスタンスメソッドをオブジェクト、CPUのタイムスライスするように、ロックを解除し、唯一の同期コードと呼ばれることができ、他のスレッドが()/のnotifyAll()を通知するのを待ち、継続して再びCPUを取得します

2.3.6収量

唯一のタイムスライスが優先度(優先順位)をスレッドに割り当てられているので、静的メソッド、一旦、同じスレッド競争CPUを放棄

2.4デーモンのデーモンスレッド

スレッドには、setdaemon(真)デーモンスレッドでは、メソッド呼び出しの前に)(その開始を設定します

デーモンスレッドがデーモンスレッドの終了後に自動的に終了しますが、finallyブロックは実行されません

3.Javaメモリモデル(JMM)

複数のスレッドは、オブジェクトの振る舞いを呼び出して、ランタイム環境と交互運転中のスレッドのスケジューリングを考慮しないと、追加の同期を必要としない、または連携呼び出し側に他の操作を実行した場合、同じオブジェクトにアクセスするときあなたは、このオブジェクトがスレッドセーフであると、正しい結果を得ることができます。 - 「Java仮想マシンの深い理解」

マルチスレッド条件は、複数のスレッド間の相互通信を含むであろう。パフォーマンスの最適化のために、また、プロセッサの問題を並べ替える並べ替えコンパイラディレクティブと命令に関する。

主な理由は、これらの問題の主なスレッドセーフなメモリとデータメモリワークスペース矛盾理解がJMMの中核です

3.1メモリモデル抽象的構造

並行プログラミングは、主に2つの問題、すなわち、スレッド間通信と同期に対処する必要があります。共有メモリとメッセージパッシング:通信用の2つの主要な機構があります。Javaは、共有メモリのアプローチを選択します。

3.1.1共有変数タイプ

すべてのインスタンスのフィールドのJavaプログラムにおいて、静的フィールドおよび配列要素は、ヒープメモリ(すべてのスレッドがアクセス、共有することができる)であり、定義された変数、パラメータ、およびメソッドローカル例外ハンドラパラメータは、スレッドではありませんルームシェア。データは、スレッドの安全性の問題ではなく、共有データスレッドセーフ問題なく共有されます。

3.1.2抽象構造モデル

処理速度とメインメモリは、CPUの速度を読み書き桁ではない、この大きなギャップをバランスさせるために、各CPUのためにそこにキャッシュされます。

共有変数が読み取られ、ワーキングメモリに使用変数後に書き込み動作している、第一各スレッドはそれ自身のワーキングメモリを有し、メインメモリに配置され、それらの作業メモリにコピーされているメインメモリ共有変数にありますコピー、およびいくつかの点で、可変ワーキングメモリのコピーがメインメモリにライトバックされます。

スレッドAタイムリーに更新されたデータは、スレッドBが「ダーティリード」現象に登場古いデータを、読まれる時に、メインメモリにライトバックされていない場合。

3.2並べ替え

パフォーマンスを向上させるために、多くの場合、並べ替えコンパイラやプロセッサの命令を持って、コンパイラとリオーダーでプロセッサは、我々はデータの依存関係を遵守し、コンパイラとプロセッサは、2つのデータ依存関係の操作が存在を変更しません実行順序

3.3は、事前発生します

スレッドはプログラマによってメモリの視認性を確保するために事前発生関係を設けてもよい横切っJMM:書き込み動作が発生し、前の関係はaとbの間に存在する場合、スレッドは、異なる操作及びBの動作であるが、スレッドBを読み取ります動作は可視動作Bであることを保証するために、プログラマにスレッドの実行が、JMM

基本原理:彼らはプログラムの結果を変更しないでください(正しく同期プログラムシングルスレッドとマルチスレッドのプログラムを参照)、コンパイラやプロセッサを最適化する方法を行います。次のように主なルールは以下のとおりです。

プログラムシーケンスは、ルール:各操作は、スレッドが発生する前に、後続の操作スレッドに

2モニタロック(同期)ルール:ロック解除するためのモニタは、事前発生モニターの後続のロック、スレッドは、データスレッドのスレッドAの代わりに、変更をロックするためのロックが起こる前に、スレッドBを解放します可視B

3.4同時データセキュリティ

JMMの抽象構造からメモリhehappens-前のルールは、複数のスレッドが、アトミックから発注を開発する必要があるときに、データダーティリードの問題が発生する可能性があり、シングルスレッドの場合、データなしのセキュリティ上の問題はなく、複数のスレッドに見えます考慮すべき視認性の三つの側面

4Synchronizedオブジェクトロック機構

同期4.1

同期方法

//インスタンスメソッド、オブジェクトロックpublicsynchronizedvoidmethodクラスのインスタンス(){}

//静的メソッド、ロックpublicstaticsynchronizedvoidmethodクラスクラスのオブジェクトです(){}

シンクブロック

//ロックされたクラスのインスタンスオブジェクトは(この){}同期されます

//ロックされたクラスは、クラスのオブジェクトが同期される(Object.classを){}

//オブジェクトのロックされた構成例が同期され(newObeject()){}

スレッド間の同期関係を確保するために、つまり、まだロックされるロックは、その後、クラスオブジェクトである場合、オブジェクトの新しい複数のインスタンスにもかかわらず、彼らはまだ同じクラスに属します。注意してください。

4.2オブジェクトのロック機構

4.2.1 Javaオブジェクトヘッダ

同期は、オブジェクトのロックを取るようにすると、実際にオブジェクトモニターを獲得しています。オブジェクトの符号と同様モニタ、このフラグは、オブジェクトヘッダJavaオブジェクトに格納されています。オブジェクト・ストレージ・ハッシュコード、年齢や世代ロックフラグのデフォルトのJavaオブジェクトのマークのWord前進。

モニターは、スレッドプライベートなデータ構造です。各オブジェクトはロックされ、店舗の所有者フィールドに同時にモニタで、関連するモニタを一意にロックがこのスレッドを占有していることを示す、ロックを所有するスレッドを識別する。

達成するために、同期4.2.2

修飾されたバイトコード・ファイルは、方法はmonitorenterとmonitorexit包装される、方法を同期:同期同期を使用する場合、同期コードブロックは、第1の命令monitorenter、monitorexit出口コマンドを実行しなければならないの後、鍵が対象となりますスレッドがダウンして継続して監視なったときにそう、彼らは待つことができ、ブロックまたはブロック同期コード同期メソッドエントリ、取得するモニターを監視し、ブロックされた状態に入りました。

データはスレッド操作がメインメモリにフラッシュされるときに、他のスレッドがロックを取得する際に、メインメモリは強制的に最新の値から取得されますロックを解除します

5ロック

いくつかのタイプに分けることができ、さまざまな方法でロック、以下は一般的な分類をまとめたものです。

5.1共有ロック排他ロックVS

また、排他ロックはロックが唯一のスレッドによって保持されることを意味し、排他的ロックと呼ばれます。スレッドT Aのデータと排他ロックした場合、他のスレッドは、もはや唯一つのスレッドが同時にターゲットモニタ(モニタ)を取得することができますロックのいずれかのタイプを追加することはできません、他のすべてのスレッドをブロックしながらすることでしょうロック。データを読むことができるだけでなく、データを変更する排他ロックのスレッドを取得します。実装クラスでは、同期中にJDKとロックJUCは、ミューテックスです。

共有ロックは、ロックが複数のスレッドによって保持されることを意味します。プラスデータに糸Tがロックを共有している場合、他のスレッドが唯一のシェアプラスロックは排他ロックを追加することはできません。スレッドはデータのみを読み取ることができ、共有ロックを取得し、データを変更することはできません。ロックが共有ロックである読み取るReentrantReadWriteLockように、書き込みロック排他ロックである、一般的なミューテックスと比較して並行性が大幅に改善されています。

5.2 VS楽観、悲観的ロックロック

同じデータの同時動作のために、データを変更する別のスレッドでなければならないデータの使用に悲観的ロックそのものを検討し、それが最初のデータを取得する時にロックされ、データが別のスレッドによって変更することができないことを確認してください。JDKは、同期とJUC Lock実装クラスです。

オプティミスティック・ロックは、更新データが他のスレッドの更新は、このデータが存在しない判断する前に、それは時間だけで、ロックを追加しませんので、彼らは、データの使用中のデータを変更する他のスレッドを持っていないと思います。CAS JUCパッケージを使用して実装されたCAS、クラスの実装クラスCASスピン上のJavaアトミックインクリメント操作によるロックフリーのプログラミングアルゴリズムの実装により、主に多くのがあります。

適応VS 5.3スピンロックスピンロック

ブロックまたはスイッチングスレッドがCPUの状態を完了する必要がありますJavaのオペレーティングシステムを覚ます、状態遷移は、プロセッサ時間を要します。シンクブロックの内容があまりにも単純である場合は、時間のかかる状態遷移は、ユーザーコードの実行時間よりも長くなる可能性があります。

ロックを保持しているスレッドがすぐにロックを解放するかどうかを確認するために、CPUの実行時間を与えることなく、要求ロックスピンロック・スレッドを作成します。そして、ロックは、それは非常に長い糸廃棄物のプロセッサリソースを必要な時間のスピンを防ぐためであるとき、スピンPreBlockSpinの最大数を変更することによって変更することができます

適応性スピンロックJDK1.6は、適応スピン時間(数)はもはや固定されていることを意味導入が、スピンロック時間た状態でロックされ、所有者は、以前によって決定されます。

5.4 CASE

5.4.1原則

CAS競合があるかどうかを識別するために、交換スレッドを比較して(比較およびスワップ)、競合は競合が存在しなくなるまで、現在の操作を再試行するように思われました。人気のCAS(V、O、N)であると理解され、3値は次のとおりです。メモリのアドレスに格納されている実際の値V、Nの新しい更新された値; O期待値(古い値)。

VはOに等しい場合にのみ、CAS方式新しい値N原子が値Vを更新する場合(「+比較更新」は全体の動作原子である)、または何もしません。

一般的に、「更新」は、進行中の再試行です。

5.4.2問題と解決策

ABA:BにAへのCASの手順、古い値ならば、その後、Aに、単に古い値とCASの検査は何の変化はまだありませんが、実際には変更をした明らかにしません。ソリューションは、共通のデータベース楽観的ロックの道をたどるバージョン番号を解決することができます追加することができます。

長いサイクル時間の大きな支出。CAS操作は、長い時間のために成功しなかった場合、それは非常に大きなCPUのオーバーヘッドをもたらすために、スピンアップすることがあります。

共有変数はアトミック操作を保証することができます:一つの解決策は、すなわちクラスのメンバ変数は、これらの共有変数である、複数の共有変数を統合するためにオブジェクトを使用することです。このオブジェクトは、原子性を保証することができCAS動作が行われます。原子AtomicReference基準原子間のオブジェクトことを確実にするために提供しました。

5.5何のロックはVS VS VSヘビー級軽量ロックロックをロック偏っていません

コンテンツの同期コードブロックがあまりにも単純である場合は、時間のかかる状態遷移は、長い時間よりもユーザーコードの実行である可能性が高いです。「このアプローチはいくつかの方法初期同期するだけでなく、同期の低効率のJDK 6の前に理由が同期されます。このオペレーティングシステムのミューテックスのロックロックに依存しては、我々は「ヘビー級ロック」と呼んで実現種、JDK 6が得られるとロックがパフォーマンスを低下させる解放するために消費をもたらし、「偏ったロック」と「軽量ロック」の導入。

、バイアスされ、軽量でヘビー級のロックロックをロックし、何のロック:先にマークWordのJavaオブジェクトのローからハイへのレベルではない、四つの状態がロックを記録。のみアップグレードすることができますロック状態がダウングレードすることはできません。

ロックなし:なしリソースにはロックをロックしていない、すべてのスレッドがアクセスしないと、同じリソースを変更するが、同時に一つだけのスレッドが正常に変更することができます。ロックフリーな実装であるCASの理論と応用。いいえロックは完全にロックを置き換えることはできませんが、いくつかのケースでロックフリーのパフォーマンスは非常に高いです。

バイアスロック:いくつかの同期コードはスレッドによってアクセスされた、スレッドIDは、スレッドのロックを支持してマークワードに格納され、自動的にロックを取得するためのコストを低減すること、ロックを取得します。唯一の経験、他のスレッドは、偏ったロックを競うロックがロックする傾向にあるスレッドのリリースでは、スレッドが偏っロックを解除するためのイニシアチブをとるません保持しようとします。

軽量ロック:ロックがバイアスロック時間である場合、別のスレッドによってアクセスされ、それは軽量バイアスロックロックにアップグレードされ、別のスレッドが、スピンの形でロックを取得しようとするブロックしないことにより、性能を向上させます。

ヘビーロック:現在のスピンによって一つだけ待機中のスレッド、スレッドが待機であれば、ロックは、バイアスされた固定時間です。しかしとき、スピンの一定数、またはロック、スピンを保持しているスレッドよりも別の第三の訪問中に、軽量の重量級のロックロックのエスカレーション。スレッドがブロックされているロックを所有するスレッドに加えて。

6volatileキーワード

6.1はじめに

揮発性変数は、各スレッドは、このようにデータをダーティ・リード現象を回避する、変数の最新の値を取得できることを保証するために修飾することができます。ブロッキング同期に関して同期(競争の激しい状況でスレッドがヘビー級ロックにアップグレードされます)、揮発性間違いなくJava仮想マシンが提供する最も軽量な同期メカニズム。

6.2原則(キャッシュ・コヒーレンシ)

それは共有変数の揮発性の修正に書き込まれます際にアセンブリコードを生成することより、命令ロック接頭辞になります。

ロックプレフィックス命令は、プロセッサキャッシュのライトバックメモリを引き起こします。

プロセッサのキャッシュメモリが失敗に終わることができ、他のプロセッサのキャッシュに書き戻されます。

プロセッサは、ローカルキャッシュの無効化に見つけたとき、それはほとんどの現在の値を取得することができ、メモリから変数データを、再読み込みします。

6.3は事前発生関係

volatileフィールドへの書き込み、たまたま-前にこの揮発性の分野では、後続の読み取り;各スレッドは、最新の値、データのすなわち「可視性」を得ることができることを確認してください。

揮発性メモリセマンティクスを達成するために、コンパイラ生成バイトコードは、プロセッサ並べ替えの特定の型を阻害する命令シーケンスメモリバリアに挿入されます。揮発性ドメイン操作前の命令は、揮発性のドメインの後に作動するように並べ替えることができません。

7finalキーワード

修正されたコンテンツを表現するための最終的な修飾することができる変数、メソッド、クラスが割り当て一度変更されず、このプロパティが変更価値があるかもしれ

7.1 final変数

最終的に初期化されていないシステムは暗黙的に初期化されていない場合には

7.1.1最終メンバ変数:

変更されたクラス変数(静的変数):あなたは、静的な初期化ブロック内の初期値を指定するか、またはクラス変数の宣言時に初期値を指定して、2つのだけの場所のいずれかで指定することができなければなりません。

修飾された変数(非静的変数)の例:非静的初期化を阻止するために必要では、インスタンス変数またはステートメントは、コンストラクタで初期値を指定し、3箇所で指定することができます。

7.1.1最終ローカル変数:

再びそれを変更することはできません明示的に使用する前に初期化する必要があり、初期化の後ろにされています

7.2最終的な方法

修正方法は、メソッドをオーバーライドすることができない、上書きすることができます

7.3 finalクラス

変更されたクラス、クラスは継承できません

そして7.4最終並べ替え

7.4.1最後の基本データ型

ルールを並べ替え、最終的なフィールドを書く:JMMは、(コンパイラはfinalフィールドの後に書きます、コンストラクタはバリアstorestoreを挿入する前に返却)コンストラクタ外finalフィールドを並べ替える書くために、コンパイラを防ぎます

ルールを並べ替え、最終的なフィールドを読むJMMは、ターゲットの最終フィールドを読み取る前に、すなわち、並び替え初期読み出しオブジェクト参照を禁止し、最終フィールドに含まれるオブジェクトの2つの動作を読み取る初期、最初に読み込まれるオブジェクトは、最終的なフィールドを含みます参照。実際に読み込まれたオブジェクトの存在及び最終リード対象の間接的依存のフィールドを指す、一般的なプロセッサは、二つの動作の順序を変更しないであろう。

7.4.2最終的な参照データ型

コンストラクタ外部構成された基準オブジェクトは、基準変数を割り当てる送信オブジェクトのコンストラクタ内ドメインのメンバーの最終的な修正を書き、そして、これら二つの動作は並べ替えることができません。

注:最終書き込みの並べ替えルールのドメインは、前提があることは、オブジェクトの最後のフィールドがあまりにもコンストラクタで初期化されているときに我々はオブジェクト参照を使用するようにすることができます:コンストラクタでこれがあることを任せることはできません構築されたオブジェクトは、オブジェクトのコンストラクタの前に最終的なドメインが戻り初期化されているが(他のスレッドに可視であるが、他のスレッドによって参照されるオブジェクトは、他のスレッドは、につながる場合まだコンストラクタ実行中にオブジェクトにより取得されました最後のフィールドが初期化されます)

800以上のスレッドセーフティの概要

マルチスレッドデータのセキュリティは、複数のスレッドがアトミックデータ、注文視認性の問題の治療を指し

8.1不可分

操作を指しますが中断されていない、どちらかのすべてが成功するか、失敗した実行のすべて

Javaメモリー・モデルは、8つのアトミック操作定義:ロック(ロック)、アンロック(ロック解除)、リード(読み出し)、負荷(荷重)は、(使用)を使用し、(割り当て)を割り当てる、店舗(店舗)、書き込み(操作)

一般的には、基本データ型は、読んでいるとみなされ、アクセス原子性を書くことができます

我々はアトミック操作がロックの広い範囲を使用し、アトミック操作のロックを解除することができます必要がある場合は、その主な成果は同期されています

揮発性の保証アトミックには、次の2つの規則を満たしている必要がありましょう:演算結果は、変数の現在の値に依存して、または1つのスレッドのみ変数を変更することを保証することはできません。変数は、他の状態変数一定の制約に参加する必要はありません

8.2秩序

同期セマンティックスレッドは読み取り専用と共有変数への書き込みアクセスが、そうは順序を同期しているときに実行「シリアル」が必要です。

順序を持つ、セマンティック揮発性disableコマンドの並べ替えを含みます。揮発性の変数は、代入の周りのメモリバリアを追加、並べ替え、メモリバリア命令の前に位置する後続の命令はありません並べ替え

8.3可視性

メインメモリに変数の同期を共有する場合、変数の最新の値がスレッドがロックを取得し、メインメモリから共有されます取得、ロックが解除されます。このように、可視性と同期。

揮発性では、メモリの可視性を達成するために添加することにより、命令の命令をロックします

8.4概要

同期:アトミック、順序と可視性を持ちます。

揮発性:特定の順序と可視性

ます。https://www.jianshu.com/p/007f95307e9eで再現

おすすめ

転載: blog.csdn.net/weixin_34288121/article/details/91163529