-
1、なぜロック?
-
ロックを達成するための2、基本原則
-
2.1、揮発性
-
2.2、同期
-
2.3 CASE
-
3、ロックのJavaの実現
-
3.1、キューシンクロナイザ(AQS)
-
4、ロックのユースケース
-
4.1、原理と使用のConcurrentHashMapの
1、なぜロック?
ロック - 一貫性のないデータの問題によって引き起こされるダーティリードの同時実行性を解決するために。
ロックを達成するための2、基本原則
2.1、揮発性
Javaプログラミング言語は、スレッドが正確かつ一貫して更新されたスレッドだけでは、この変数を介して取得する排他ロックを保証しなければならないことができる共有変数を確保するために、共有変数にアクセスすることができます。Java言語は、揮発性の提供、およびいくつかのケースではロックよりも便利であることを。
揮発性マルチプロセッサの開発で共有変数の「可視性」を確保します。視認性は、スレッドが共有変数を変更するとき、他のスレッドがこの変更の値を読み取ることができることを意味します。
結論:それはスレッドコンテキストの切り替えやスケジューリングを起こさないため、揮発性の変数修飾子が正しく、そしてそれは、同期の実行のコストよりも低い場合。
2.2、同期
ロック機構を介して同期同期。
同期を達成するために、同期の基礎の使用を初めて目:Javaの各オブジェクトは、ロックとして使用することができます。
以下の三つの形式で特定のパフォーマンス。
-
通常の同期方法のために、ロックオブジェクトの現在のインスタンスです。
-
静的な同期メソッドの場合、ロックは現在のクラスのClassオブジェクトです。
-
同期ブロックするための方法は、オブジェクトのロックがSynchonizedブラケットに構成されています。
スレッドは同期ブロックにアクセスしようとすると、それは最初にあなたが終了するか、例外をスローしたときにロックが解除されなければならない、ロックを取得する必要があります。
2.2.1同期の実装原理
同期同期は、ベースのモニタを実現しています。
スレッド間の同期をサポートする2つの方法を監視します。
-
排他実行
-
連携
1、Javaは相互に排他的な実行を設定する共有データにワーカースレッドを確実にするために(同期用いて得られたオブジェクトをロック)ロックを使用してオブジェクト。
図2に示すように、異なるスレッド間で動作するように通知する/のnotifyAll /待ち方法を使用して。
3は、クラスとオブジェクトをモニタに関連付けられています。
作業機を監視
-
スレッドは同期方法に入ります。
-
クリティカルセクションを実行し続けるためには、スレッドがロックモニタを取得する必要があります。あなたがロックを取得する場合は成功し、それはウォッチャーオブジェクトの所有者となります。いずれかの時間内に、スーパーバイザオブジェクトは、唯一のアクティブなスレッド(所有者)に属しています
-
監視したオブジェクトのスレッドが)(待機を呼び出すロックの解除を監視しながら、(セットを待って)セットを入力待ち状態に入るのを待つことができます。
-
他のスレッドの呼び出しは、ウェイクアップ待機しているスレッドを設定する()/のnotifyAll()インタフェースを通知し、これらのスレッドは待つ必要があるモニターがロック再獲得するために待機を実行することができ、次のコードを()。
-
同期方法が終了すると、スレッドがクリティカル領域を出て、モニターのロックを解除します。
参考資料ます。https://www.ibm.com/developerworks/cn/java/j-lo-synchronized
2.2.2同期特定の実装
1、monitorenter、明示的に実装さmonitorexit命令を使用して、同期コードブロック。
図2に示すように、暗黙的な同期方法を用いるACC_SYNCHRONIZEDマーカーを実装しました。
一例として、特定の実装を見てみましょう。
public class SynchronizedTest {
public synchronized void method1(){
System.out.println("Hello World!");
}
public void method2(){
synchronized (this){
System.out.println("Hello World!");
}
}
}
次のようにコンパイルしてjavapバイトコードの後:
monitorenter
各オブジェクトは、モニターが唯一のスレッドが所有することができ、モニターがあります。スレッドがmonitorenter命令が対応するオブジェクトのモニターを得る実行しようとすると、次のように、アクセスルールは以下のとおりです。
-
モニターに入る数が0である場合、スレッドは、モニタを入力することができ、およびモニタは番号1を入力するように設定され、スレッドの所有者を監視しなければなりません。
-
現在のスレッドがすでにモニターを所有している場合は、のみに再入力し、その後、モニタープラス1に番号を入力し、そのキーワードsynchronizedロックを達成するためには、再入可能ロックです。
-
モニターは、モニターへの数まで0に、他のスレッド、ブロックされた状態に現在のスレッドによって所有されている場合は、その後、再びモニターを取得しよう。
monitorexit
唯一の適切なオブジェクトの監視スレッドを持つものはmonitorexit命令を実行することができます。命令は、現在の監視スレッドの数に放出されたモニタマイナス1に入るたびに、その後ブロックされたスレッドがモニタを獲得しようとし、午前0時00です。
2.2.3ロック格納場所
頭部に保存されているマークのWord Javaオブジェクトにマークをロックします。
64 JVMマークWordの構造
2.2.3同期ロックの最適化
取得とリリースロックをパフォーマンスが低下するJavaSE1.6順は、「偏ったロック」との導入消費をもたらした「軽量ロックを。」
、ロックフリー状態の競争として徐々に状態、ロック状態、軽量かつヘビー級ロック状態、これらの状態をロックします傾向:JavaSE1.6では、4つの状態、ローからハイへのレベルの合計をロックアップグレードしてください。
ロックはアップグレードできますが、バイアスは軽量ロックにロックのアップグレードをロック偏ったにダウングレードすることができないことを意味ダウングレードすることはできません。このロックはアップグレードが、戦略は、効率を改善し、ロックを解除するためにロックを取得するように設計されてダウングレードすることはできません。
バイアスされたロック:
ロック競合リソースオーバーヘッド、バイアスロックの導入を低減するために、ロック競合が存在しません。
軽量ロック:
軽量ロックスレッドが交互シンクブロックで行われる適応シナリオ、。
ロック粗大化(ロック粗大化):即ちしっかり、より大きな範囲ロックに拡張連続ロック複数のロック操作のロックを解除する連結不要減らします。
ロック排除(ロック消去):コードの一部が同期を必要としますが、競争が削除されますラッチ共有データを検出することができないため、ロックのスラッシングは、実行時に仮想マシンタイムコンパイラです。
適応スピン(適応スピニング):スピン時間の適応手段はもはや固定されていないが、ロックした状態でスピン時間とロックの所有者は、前者によって決定されます。同じオブジェクトだけ成功した勝ったロックをスピン待ち、ロックを保持しているスレッドのロックが実行されている場合、仮想マシンは、これも再び成功スピンである可能性が非常に高いと思いますし、それがスピンを許可します100サイクルとして、時間の比較的長い期間などを待ちます。一方、ロックを獲得するために、将来のスピンめったに成功していない、そのためのロックは、プロセッサリソースの浪費を避けるために、スピン工程を省略することが可能になります。
ロックの長所と短所の比較2.2.4
2.3 CASE
CASは、Javaアプリケーション、すなわち比較およびスワップ、同時またはコンペア・アンド・スワップのcompareAndSetを指します。
1、CASは、アトミックオペレーションでは、メモリ位置の値を比較し、この中の他のスレッドが存在する場合、新しい値は常に、計算最新の情報に基づくものであることを確実にするために、新しい値のメモリ位置のみが等しい値であり、変更しますCASが失敗した時にこの値が変更されます。CASは、成功またはメモリロケーションが成功CASか否かを判定するための元の値を返します。
図2は、JVM CAS動作は、プロセッサ実装によって提供CMPXCHG命令の使用です。
利点:
-
リトル競争とき、小さなシステムのオーバーヘッド。
短所:
-
長いサイクル時間の大きな支出。
-
ABAの問題。
-
アトミック操作は、共有変数を保証することができます。
3、ロックのJavaの実現
3.1、キューシンクロナイザ(AQS)
(以下、同期と呼ぶ)AbstractQueuedSynchronizerキューシンクロナイザは、ベースフレームロックまたは他の同期コンポーネントを構築するために使用されます。
3.1.1は、int型のメンバー変数は、同期ステータスを示し使用。
3.1.2は、内蔵の双方向のFIFOキューロックキューのスレッドの作業を取得するために。
-
シンクロナイザは、アプリケーションノードの2種類の第1のノード点、尾を指すノードを含む、スレッドロックが取得されていないノードは、スレッドセーフ(compareAndSetTail)はキューの末尾に加えた作成します。同期キューはFIFOに従って、最初のノードが成功した同期ステータスのノードを得ることです。
-
エンド・ノードに設定されたノードを、作成するスレッドをロックするために取得できませんでした。下図のように:
-
ロックが解除されたときに最初のノードをスレッド、それ以降のノードを起動します。後続ノードは、ロックの取得に成功すること自体がヘッドノードを設定します。下図のように:
3.1.3、共有/排他ロック取得
独占:そこ一つであり、唯一のスレッドのような、ロックを取得することができます:ReentrantLockの。
共有:複数のスレッドが同時にロックを取得することができる、例えば:たCountDownLatch
独占式
-
各ノードのスピンは、自分の前のノードを観察することがある場合は、ロックを取得しようと行く、ヘッダーノードではありません。
-
排他ロック獲得処理:
共有:
-
共有と排他的な違い:
-
ロック取得プロセスを共有:
4、ロックのユースケース
4.1、原理と使用のConcurrentHashMapの
図のConcurrentHashMapクラス
ConcurrentHashMapのデータ構造
結論:ConcurrentHashMapのロックで使用されるセグメント化技術。まず、データストアのセクションに分割され、その後、ロックと時間のセグメントは、データの他のセグメントは、他のスレッドによってアクセス可能なデータにアクセスするときにロックを保持しているスレッドのデータのすべての部分を与えます。