アウトライン
上記「JDKのソースコード解析-lock&条件」ロックインターフェースの簡単な分析、主にJDK ReentrantLockの中に実装クラスが(「リエントラントロック」として翻訳することができます)。ReentrantLockの実装は、その内部同期にネストされたクラスに依存し、またAbstractQueuedSynchronizer SYNC(AQSと称する)から継承されました。また、等たCountDownLatch、CyclicBarrierを、などの他のツールの数によって複雑にするだけでなくReentrantLockのは、また、実現AQSクラスに基づいています。AQSは、多くのクラスでの礎石と契約として理解することができます。そのため、一般的にクラスで使用される分析し、契約履行の原則に先立って、AQSは、再解析後の時間はずっと簡単になるかを理解する必要があります。
AQS内側コアは、変数Stateを有し、また、ノードクラスのノードは、2つのキューを維持するメインキュー(メインキュー)のキューと条件(条件キュー)を、簡単のため、それぞれ、両方とも単一二重リンクリストとして理解することができると。
AQSは全てAQSによって提供されるインフラストラクチャ上で自分の「ゲームのルール」を開発し、その後生成、そのような他の一般的に使用されるクラスReentrantLockの、たCountDownLatch及びその他の内部のネストされたクラスの同期として、インフラのセットのようなデバイスを提供します異なる製品。そして、彼らはゲームのルールと2つのキューの状態変数の周りに動作します。
PS:もっとAQSのコンテンツとして、そのためのポイントの記事を分析する予定で、その全体の記事最初の概観。
コード分析
AQSクラスの署名:
パブリック 抽象 クラスAbstractQueuedSynchronizerは 延びAbstractOwnableSynchronizerは 実装にjava.io.Serializableを{}
直接インスタンス化することはできません、抽象クラスで見ることができます。親AbstractOwnableSynchronizer主なコードは次のよう:
パブリック 抽象 クラスAbstractOwnableSynchronizerは 実装したjava.io.Serializable { / ** *排他モード同期の現在の所有者を。 * / プライベート 過渡スレッドexclusiveOwnerThread。 // 其他代码 }
その主な内部変数exclusiveOwnerThread、所有者の役割は排他モードでスレッドをマークするで維持し、後でそれが分析に来るとき。
入れ子のクラス
AQSはそれぞれ、二つの内部のネストされたクラスを持っており、ノードたConditionObject。
Nodeクラスのコードは次のよう:
静的 最終 クラスノード{ // 共有モード 静的 最終ノードSHARED = 新しい新しいノード(); // 排他モード 静的 最終ノードEXCLUSIVE = NULL ; // いくつかの状態がwaitStatus 静的 最終 INT CANCELED = 1。; 静的 最終 INT SIGNAL = - 。1 ; 静的 最終 int型 CONDITION = -2 ; 静的 最終 INT = -3 PROPAGATE ; 揮発性 INT waitStatus。 // 先行ノード(マスターキュー) 揮発性ノードPREV; // 後続ノード(プライマリキュー) 揮発性ノード次に、 // スレッドノード 揮発性スレッドthread; // 後続ノード(条件キュー) ノードnextWaiter; 最終 ブールisShared(){ 戻り nextWaiter == ; SHARED } 最終ノード前身()がスローにNullPointerException { ノードP = PREVと、 IF(P == NULL ) スロー 新しい新規のNullPointerException(); そうでなければ リターンのp; } ノード(){ // 初期ヘッドまたはSHAREDマーカーを確立するために使用される } ノード(スレッドスレッド、ノードモード){ // addWaiterによって使用され 、この .nextWaiterを= モード。 この .thread = スレッド。 } ノード(スレッドスレッド、INT waitStatus){ // 状態で使用され 、この .waitStatus = waitStatus。 この .thread = スレッド。 } }
第二のコンストラクタを使用して、メインキューに追加、Nodeクラスはスレッドスレッドのパッケージとして理解することができます。したがって、ノードとしてキューにメインキューには、一つのモード(MODE)、ステートフル(waitStatus)スレッドがあることが理解されるであろう。
ネストされたクラスConditionObjectの:
パブリック クラス ConditionObjectのは、実装条件、java.io.Serializableの{ / ** 状態のキューの最初のノードを。* / プライベート 過渡ノードfirstWaiter。 / ** 状態のキューの最後のノード。* / プライベート 過渡ノードlastWaiter。 // ... }
条件ConditionObjectのキューの主な動作条件をあるインタフェースを実装し、ここでの唯一のクラス署名が再び後で分析を用いる場合は特に、頭と尾のノードに固定します。
主な変数
AQSコードは長いですが、以下のように、それは、メンバ変数の多くを持っていません。
// マスターノードキューヘッド プライベート 過渡 揮発ノードヘッド; // メインキューのテール・ノード のプライベート 過渡 揮発ノード尾; // 状態、コア変数AQS維持するために、 プライベート 揮発 int型の状態を、
前記メインヘッドとテールキューの先頭と末尾ノード、AQS可変状態維持のコア、及びReentrantLockのクラスクラスのようなそれぞれの機能が動作状態によって達成され、同期を実現します。
CAS操作
内部AQSは、安全でないカテゴリでCAS(コンペア・アンド・スワップ)の操作(CASは、もはやここ独自の検索を理解することができる概念を説明)のシリーズを達成します:
// 取得安全でない例として プライベート 静的 最終的な安全でない危険な= Unsafe.getUnsafe(); // メモリオフセット状態、頭、尾アドレス変数 プライベート 静的 最終 長いstateOffset; プライベート 静的 最終 長いheadOffset; プライベート 静的 最終 長いtailOffset、 プライベート 静的 最終 長いwaitStatusOffset; プライベート 静的 最終 長いnextOffset; 静的{ 試み{ stateOffset =unsafe.objectFieldOffset (。AbstractQueuedSynchronizer クラス .getDeclaredField( "状態" )); headOffset = unsafe.objectFieldOffset (。AbstractQueuedSynchronizer クラス .getDeclaredField( "ヘッド" )); tailOffset = unsafe.objectFieldOffset (。AbstractQueuedSynchronizer クラス .getDeclaredField( "尾" )); waitStatusOffset = unsafe.objectFieldOffset (ノードクラス .getDeclaredField( "waitStatus" )); nextOffset =unsafe.objectFieldOffset (ノード。クラス .getDeclaredField( "次" )); } キャッチ(例外例){ スロー 新しいエラー(EX); } } // 一些CAS操作 プライベート 最終 ブールcompareAndSetHead(ノード更新){ 戻り unsafe.compareAndSwapObject(この、headOffset、ヌル、更新)。 } プライベート 最終 ブールcompareAndSetTail(ノードは、ノード更新、期待){ 戻り unsafe.compareAndSwapObjectを(これは、tailOffsetは、更新、期待します)。 } プライベート 静的 最終 ブールcompareAndSetWaitStatus(ノードノード、 intは、期待 INTの更新){ 返す(ノード、waitStatusOffset unsafe.compareAndSwapIntを 期待し、更新) } プライベート 静的 最終 ブールcompareAndSetNext(ノードノード、 ノードは、期待 ノード更新){ 返す(ノード、nextOffset期待し、更新)unsafe.compareAndSwapObjectと、 }
内部スレッドの安全性のAQS作業の多くは、CASによって達成されます。
概要
1. AQSは直接インスタンス化できない抽象クラスです。
2. AQS内部コアは可変状態、ならびに2つのキュー維持メインキュー(メインキュー)のキューと条件(条件キュー)。
3. AQSは、インフラストラクチャのセットを提供し、ReentrantLockのAQSおよび他のクラスは、通常クラスSyncの内側にネストによって継承され、同期クラスで、自分の「ゲームのルール」を開発します。
この記事では、概要AQSを提供し、その後、実装原理の詳細な分析を行いました。また、それは別々に分析しない状態変数long int型とAQSのタイプであることを除いて、AQSと実質的に同一であるクラスAbstractQueuedLongSynchronizerがあります。
PS:以下のリンクでも良い書かれたいくつかの記事があります。
https://www.cnblogs.com/liuyun1995/p/8400663.html
渇望する愚か者であれ。
PS:この記事では、最初の公開マイクロチャネル番号] [WriteOnReadに登場しました。