ロック原則

ロック

同期制限:ロックを取得するためのスレッドを試み、ロックが取得がブロックされている場合よりも小さくなります。あなたがロック・スレッドを取得する場合それ以外の場合はロックを取得するために、他のスレッドの試行を待っている必要があり、現在のスレッドの例外がない限り、スリープ状態に入るか、ブロックされました。今回は、ロックを使用する必要があります。

AQS

AbstractQueuedSynchronizerは、AQSをいうコンテナフレームロックと同期を構築するために使用されます。実際にはクラスの多くは、同時パッケージAQS構造物、例えばReentrantLockの、セマフォ、たCountDownLatch、ReentrantReadWriteLock、FutureTaskなどに基づいています。AQSは、同期コンテナ設計の細部の多くを解決します。

FIFOキューを使用してAQSがロックを待機中のスレッド、キューヘッド「センチネルノード」と呼ばれるノードまたは「ダムノード」のキューを表し、それがどのスレッドに関連付けられていません。待機中のスレッドに関連付けられた他のノードは、各ノードは、待機状態waitStatusを維持します。
ここに画像を挿入説明
AQSは存在の状態を示すフィールドでもある状態が、例えば、それはReentrantLocky表す数リエントラントスレッド・ロックを、ライセンスの残り数を表すとセマフォ、FutureTaskタスクは、その状態によって表されます。状態更新変数の値は、CASアトミック更新操作の動作を保証するために使用されます。

ReentrantLockの内部構造

非株式ReentrantLockのロックのデフォルトの実装でなく、ロック公正に設定することができます。

AbstractQueuedSynchronizerはAbstractOwnableSynchronizerを継承し、このクラスでは唯一の変数ました:exclusiveOwnerThread表し、ロック・スレッドが現在占有され、対応するGET、セット方法を提供します。

ReentrantLockの内部構造:
ここに画像を挿入説明

ステップ

手順は以下のとおり:

  1. 0に1を入れて、それが設定されている場合、CASは、(現在のロックが占有されていないを表す)の状態が0であるか否かを決定するために、ロックを取得しようと試みます。そして、ロック取得の成功を示す、スレッド排他ロックの現在のスレッドを設定します。
  2. ロックを取得しようとします。彼ら自身が示す、アップデート状態フィールドを占領した場合、再び獲得するために、スレッドの試みを取得し、それが0であれば、状態フィールドをチェックし、ロックが占有されていないことを示し、その後、占有しようと、そうでない場合はゼロで、現在のロックを確認できませんでした、自分自身を占領していますロックの数を再入力してください。
  3. チームの中へ。あなたはまだ取得する場合は、エンキュー操作を失敗しました。キューが初期化されていないで、テール== nullは、その古典スピン、最終的に初期化キューによってアトミック操作をノンブロッキングスレッド+ CASの組み合わせが存在します。また、チーム内の他のスレッド。
  4. ハング。B及びCを順次acquireQueued行う(最終ノードノード、INT引数)されています。このアプローチは、スレッドは、障害が中断される場合は、ロックを取得しようとするにチームを聞かせています。チームへのスレッドがその前身のノードの状態が信号であることを前提にハングアップすることができた後、その意味は「兄弟の前に、こんにちは、あなたはチームのロックアウトされた場合は、私を目覚めことを忘れない!」です
  5. リリースが成功した場合、ロックを解除しようとするかどうか、そして、ヘッドノードならばスレッドが目を覚ますと、ヘッドノードの状態は、SIGNAL、次のノードが関連付けられている表示します。

ステップ1

まず、CASと操作0が1に設定されている場合、(現在のロックを示すが占有されていない)状態が0であるか否かを判断するには、それを入れ、ロック取得成功を示す、現在のスレッドのスレッドの排他ロックを設定します。複数のスレッドが同時に同じロックを占有しようとすると、CAS操作は素直に行く並ぶようにだけ残して、成功した操作のスレッドを保証することができます。

注:ちょうど0に、ロック状態セットをロック・スレッドのリリースを保持した場合に並んで待っている間、ここに反映されている「不公平」とは、「スレッドが直接、その後、ロックをつかむために、新しいスレッドを目覚めていないロック「キューをジャンプします。

ステップ2

現在のスレッドが3つのロックと競合する場合は、仮定するスレッドA CAS操作は他の中に入った後、BとCが障害状態に設定されているスレッド、リターンのロックを取得するには成功し、幸せでした。私たちは、取得を見下ろします。

ロックを取得しようとします。状態フィールドをチェックし、それが0であれば、ロックが占有されていないことを示し、その後、占有しようと、そうでない場合はゼロで、現在のロックを確認し、彼ら自身が占領した場合、自分自身を占有され、アップデート状態フィールドには、再入国ロックの数を示します。上記のポイントは成功していない場合、それはfalseを返し、ロックが失敗した取得。あなたがロックを取得しようとすると成功すると、この方法は、直接返します。

ステップ3

チームの中へ。上記Aのスレッドロックに既に占有するので、B及びCにtryAcquireが失敗行い、待ち行列。スレッドがロックA死んだリンクを保持する場合は、BとCは中断されます。B、Cのスレッドはキューを試み、そしてキューは、テール== nullに初期化されていない、それは少なくともENQ(ノード)でスレッドを持つようになるだろう。私たちは、中(ノード)ENQに来て、同じ時間を想定しています。それはその古典的なスピン+ CAS組合せを具現アトミック操作を非ブロッキング。CASの使用にcompareAndSetHeadクラスを達成するために危険なので、一つのスレッドだけが正常にヘッドノードを作成します操作しています。成功したスレッドB、そしてBを仮定し、Cは、サイクルの第2ラウンド、両方のスレッド内の尾もはや空、他に行くを開始します。そのBスレッドcompareAndSetTailが成功したと仮定すると、あなたはまた、循環の第三ラウンドを必要とするため、チームの失敗にB、Cに戻ることができます。最終的にはすべてのスレッドが正常にチームにすることができます。

場合B、Cキューには、キューAQSは次の
ここに画像を挿入説明
ステップ4

ハング。B及びCを順次acquireQueued行う(最終ノードノード、INT引数れます )。このアプローチは、スレッドは、障害が中断される場合は、ロックを取得しようとするにチームを聞かせています。
チームへのスレッドがその前身のノードの状態が信号であることを前提にハングアップすることができた後、その意味は「兄弟の前に、こんにちは、あなたはチームのロックアウトされた場合は、私を目覚めことを忘れない!」です shouldParkAfterFailedAcquireは最初、彼らは真のリターンを満たしていれば、現在のノードの前駆体の状態は、要件を満たすかどうかを決定しますので、その後、parkAndCheckInterruptを呼び出し、自分自身をハングします。見た目前駆体ノードがある、ない場合は> 0(中止)、あなたは、前駆体ノードステータスがSIGNALに設定されますされていない場合、前駆体の要件を満たすために最初まで前方横断している場合。状態はSIGNALノード前駆体ではない場合、プロセス全体を通じて、そしてあなたの心の自身の平和は、同時にあなたは競合ロックしようとする機会がないかどうかを確認しようとすることができ、安心ポイントを見つける必要保留、中断することはできません。
ここに画像を挿入説明
ステップ5

次のようにtryReleaseプロセス:現在のスレッドがロックを保持してロックを解除した場合は、例外がスローされます。ロックを保持している場合、0はロックが正常に解除されていることを示している場合状態計算値は、0でリリースし、その後自由戻って、排他的なスレッド、最後に更新された状態値を空にします。

リリースが成功した場合、それは次のノードに関連付けられている場合、ヘッドノードのステータスがSIGNALで閲覧リリースがロック解除失敗に偽を返すのに失敗したのであれば、スレッドの最初のノードがウェイクアップしています。ここでは、各時間しか想起ノード次のスレッドの最初のノードに関連付けられていることが分かりました。

フェアロック

ロック状態の状態を確認するために行くが、直接的aqcuire(1)、さらに説明を実行しないであろう時にロックを取得するために、その資本で異なる公正かつ不公平ロックロック。

  • タイムアウトメカニズム
  • CLHキューロック

https://blog.csdn.net/qq_33945246/article/details/104037001

https://www.jb51.net/article/105762.htm

公開された67元の記事 ウォン称賛32 ビュー60000 +

おすすめ

転載: blog.csdn.net/weixin_43751710/article/details/105080610