Java仮想マシンの深い理解 - 章XIII - 効率的な同時実行

スレッドセーフ

複数のスレッドがオブジェクトにアクセスするときは、オペレーティング環境でこれらのスレッドのスケジューリングを考慮していないと交互に行い、地域の呼び出しで追加の同期、または追加の協調作業を必要としない場合、オブジェクトの振る舞いを得ることができます呼び出します正しい結果は、オブジェクトは、スレッドセーフです。

Javaスレッドセーフ

データ分類共有クラス5の各種動作:

  1. 不変:不変オブジェクトは、スレッドセーフでなければなりません。基本データ型は、最終的な不変として定義されます。文字列は、数値、ロングと他の値は不変ですが、原子の数のAtomicIntegerは不変クラスです。
  2. 絶対スレッドの安全性:どんなにランタイム環境、追加の同期化措置は必要ありません。しかしVectorクラスは、そのメソッドが同期と組み合わせているので、スレッドセーフですが、このような次の2つのスレッド、削除された要素のアクセス素子と外側にそれを呼び出すので、外が同期でない場合、それはちょうどへのアクセスを作れば要素とエラーを削除します。だから、ベクトルは絶対スレッドセーフではありません。
  3. 相対的なスレッドの安全性:オブジェクトの個々の操作はスレッドセーフであることを保証します。ベクターは、比較的スレッドセーフであるような。
  4. スレッド互換性:オブジェクト自体はスレッドセーフではありませんが、スレッドの安全性を保証することができ、同期によって呼び出されたとき。ArrayListのとHashMapのような。
  5. スレッド敵対:同期の措置をとるかどうか、彼らはマルチスレッド環境で並行コードを使用することはできません。スレッドが中断し、一回の同時実行を再開操作しながら、スレッドのとおり一時停止()と再開()メソッドは、同期はデッドロックの危険性があるかどうかではありません。それはあなたが履歴書の前にブロックされたスレッドロックを一時停止取得したい場所を再開することにより、スレッドは、デッドロックが発生した場合、(再開しない限り、ロックが保持しているロックの解除を中断しない)自体を中断中断スレッドです。参照https://www.jianshu.com/p/7a123f212ca1を

スレッドセーフな実装

ミューテックス同期

ミューテックスは、同期を達成する手段です。また、同期、ペシミスティック・ロックをブロックとして知られ、その性能劣化をブロックし、ウェイクアップする必要があります。かかわらず、共有データは、競合が発生しロックする必要があるかどうかの。

相互排除の最も基本的な手段が同期されます。それがロックを解放するまでブロック同期とmonitorenterのmonitorexit、monitorenterを実行する際に、既にインクリメントされ、独自のを保持するか、ロックカウンタを保持していない場合は、ロックを取得しようとする試みの周りに形成することになる、実行monitorexitは、マイナス1になります0 。あなたがロックを取得するために失敗した場合の状態をブロックされます。

さらに、そこにラインの再入が設けられており、(ReentrantLockのの)JUCの再入可能ロックをsynchronnizedが、コードが異なる言い回し、ミューテックスのためのレベルのAPI(ロックや方法フィッティングのtry / finally文が実装されているアンロック)、ありますネイティブ構文レベルのミューテックス。3つの以上の高度な機能をRenetrantLock:

  • 割り込み待ち:ロックを保持している長いスレッドがロックを解除しない場合は、ロックを待っているスレッドが他のものに対処する代わりに待ってあきらめることができます
  • フェアロック:複数のスレッドがロックを取得するためのアプリケーション年代順に、ロックを待ちます。各ロックはスレッドを待ってロックへのアクセス権を持っているのではなく、公正で、非公正ロックを同期
  • 結合条件をロック:リエントラントは、複数の条件オブジェクトをバインドすることができますが、余分なロックを追加する必要がある場合、同期や複数の条件に関連していることが、リエントラントのみ複数の呼び出しのnewCondition。

ノンブロッキング同期

オプティミスティック・ロック。競合がある場合は、競合、(一般的な補償は、それが成功するまで再試行を続けている)を補償する他の措置をとるために、共有データにはスレッドが存在しない場合は、その操作を実行し、操作が成功したと同時方式。だから、スレッドが中断されて送信されません。

あなたは意味がない相互排他性を確保するため、これを成し遂げるためにハードウェアを必要とするために、同期を使用する場合、オプティミスティック・ロックの操作とその競合検出を確保する必要性が、アトミックです。CASコマンド。

CAS 3つのオペランド:メモリアドレスA、古いOの期待値、新しい値N Aがあれば、Vは新しい値Nに古い場合は期待値Oに沿って更新され、古い値Oを返すされている場合にのみ、満たしていない何のアップデートを提供しません。この操作はアトミック操作です。

いいえ同期方式ません

保証スレッドの安全性は必ずしも同期させるために、2つの間には因果関係は必要ありません。次に、本方法は、任意の同期せずに、共有データを含まない場合。例えば、コードは、次の2種類が本質的にスレッドセーフです。

  • リエントラントコードされている:純粋なコードとしても知られる、任意のタイムコード実行で中断することができ、制御が返された後にエラーなし(再帰呼び出し自体を含む)は、コードの別の部分、元のプログラムを実行するためにオン。リエントラントコードはスレッドセーフで、順番に、そうではありません。決意の簡単な方法がある:方法は、結果は予測可能である返す限り、同じ入力データが同じ結果を返すことができるように、それは要件リエントラントを満たす場合。例えば、使用状態量を呼び出さずに、非リエントラントコードヒープデータ共通のシステム・リソースに依存しないパラメータです。
  • ローカルストレージをスレッド:必要なコードデータは他のコードと共有する必要がある場合は、これらの共有データが同じスレッドで実行されるために、あなたがそのコードを確保することができるかどうかを確認。コンシューマ・キューが保証されているように、このようなプロセス内のスレッドの消費量は、スレッドの要求に対応するWebサーバで、特に、完了です。

ロックの最適化

ロックの最適化技術:アダプティブスピンロックの除去、ロック粗大化、軽量ロック、偏ったロック、

適応とスピン - スピンロック

ミューテックス同期パフォーマンスのオーバーヘッドは、モードを完了する必要がカーネルに、スレッドを中断し、再開の最大のです。共有データをロック状態のほとんどは短時間しか持続し、それ価値がないが、サスペンドとレジュームするには、この時間がかかるので、あなたは、ロック要求の後ろに取得することができ、「何を待っている、」しかし、していないプロセッサの実行時間をあきらめるだけで、スピンロックと呼ばれる自由な流通(スピン)を行います。

スピンはブロックされて交換することはできません。時間はスピンスレッドのサスペンドとレジューム時間のオーバーヘッドのコストを超える場合には、プロセッサリソースを無駄に消費します。デフォルトのスピン10回は、-XXことができます:PreBlockSpin変更を。スピンロックスピン時間の導入後JDK1.6が固定されていませんが、ロックされたロックスピン時間で同じ時間と国家の所有者が決定します。最後のスピンとのスレッドが実行されて成功した場合、スピンが成功したとみなされますので、スピンロックが直接省略可能直接スピンのために稀に成功した未来であればスピンは、長く続きますハング。

ロック排除

ロックがあっても、時間をコンパイルコード同期のための多くの要件を排除する、それは共通のデータロック競合が検出された手段を排除するために存在していません。ロックを安全に除去することができるようにStringBufferが基準concatStringに逃れられないであろう同期ブロックの例を追加し、他のスレッドは、彼にアクセスすることができません。

パブリック文字列concatString(ストリングS1、文字列s2、ストリングS3){ 
        StringBufferのSB = 新規のStringBuffer(); 
        sb.append(S1)。
        sb.append(S2)。
        sb.append(S3)。
        返すsb.toStringを(); 
}

ロック粗大化

原理的には、同期範囲が小さいことが推奨され、専用の同期は、共有データの実際の範囲で起こります。あなたは何度も、競争でない場合は、forループでロックされて見えても、一連の操作で同じオブジェクトのロックを解除、またはロックした場合は、頻繁に相互排他同期は、パフォーマンスの損失につながることができます。例えば追記上、仮想マシンは、最後の追加する追加拡張の第1の範囲内にロックされます。

軽量ロック

従来の用語を使用して達成することが比較的軽量のオペレーティングシステムのロックミューテックスのロックで、伝統的なヘビー級ロックがロックされています。

あなたはCAS操作対象ヘッダフラグと、軽量ロックをでロックされていないロックオブジェクトヘッダフラグを取得するスレッドを起動した場合、オブジェクトのロックを保持します。更新に失敗した場合、そうでない場合はロックが他のスレッドによって占めていることを示す、現在のスレッドのスタックフレームへのオブジェクトマークワードポイントはショーはすでにロック、同期ブロックへの直接アクセスを持っていると判断されます。以上の2つのスレッドがロックと競合した場合、ロックは軽量ヘビー級のロックになります。

軽量ロックに基づいて経験的データである、「存在しない競争を同期化され、全体のサイクルの中で最もロック」の同期性能を向上させることです。何の競争、そしてCAS操作は相互に排他的なオーバーヘッドの使用を回避使用はありません。

バイアスされたロック

ロックは、最初のスレッドに有利にバイアスされる次の実行中に、ロックが他のスレッド、同期する必要はありません保持してバイアスされ、ロッキングスレッドによって取得されていない場合は、それを取得します。あなたが偏っロックを保持してきた場合は、オブジェクトがロックされたり、軽量ロック状態に変換ロックが解除されているかどうかに応じてロック。

 

おすすめ

転載: www.cnblogs.com/yjou/p/11270307.html