Javaの並行処理--Condition実装分析

条件の実装分析

操作は非常により合理的な内蔵型シンクロナイザとして、ロックを獲得に関連した条件を必要とするのでConditionObjectの同期は、AbstractQueuedSynchronizer内部クラスです。各オブジェクト(以下、待ちキューと呼ばれる)条件キューを含む、キューは、オブジェクト待機条件/通知機能を実現するために重要です。

待ち行列

待ちキューはFIFOキューで、キュー内の各ノードは、スレッドへの参照を含むスレッドがCondition.await()メソッドは、スレッドの意志を呼び出す場合、スレッドは、オブジェクトの状態のスレッドを待っていますロックを解除し、ノードは待ちキューに参加するように構成され、待機状態に入ります。実際には、ノード定義の定義は、ノードの同期を多重化、即ち、同期キュー待ちキューと静的インナークラスAbstractQueuedSynchronizer.Nodeノードタイプが同期です。

条件を含むキューは、条件は、最初のノード(firstWaiter)及びテールノード(lastWaiter)を有しています。現在のスレッドがCondition.await()メソッドを呼び出し、現在のスレッドは、ノード、尾からノードを構成され、下に示されている待ち行列の基本構造を待って、待ち行列に加えます。

ここに画像を挿入説明

図に示すように、条件は、エンドノードに基準端を有し、新しいノードは、エンドノードに元のテール・ノードnextWaiterそれを、そして更新をポイントする必要があります。await()メソッドのスレッドを呼び出すと、プロセスはスレッドセーフ確保するためのロックであると言うことですロックを取得したスレッドでなければならないため、上記参照ノード更新プロセスは、CASの保証を使用していません。

モニター上のモデルのオブジェクトは、オブジェクトが同期キューと待ち行列、及び契約ロックを有している(より正確には、シンクロナイザ)を以下に示すような対応関係で同期キュー待ち行列を複数有し、 。

ここに画像を挿入説明

如图所示,Condition的实现是同步器的内部类,因此每个Condition实例都能够访问同步器提供的方法,相当于每个Condition都拥有所属同步器的引用。

等待

调用Condition的await()方法(或者以await开头的方法),会使当前线程进入等待队列并释放锁,同时线程状态变为等待状态。当从await()方法返回时,当前线程一定获取了Condition相关联的锁。

如果从队列(同步队列和等待队列)的角度看await()方法,当调用await()方法时,相当于同步队列的首节点(获取了锁的节点)移动到Condition的等待队列中。

ConditionObject的await方法:
ここに画像を挿入説明

调用该方法的线程成功获取了锁的线程,也就是同步队列中的首节点,该方法会将当前线程构造成节点并加入等待队列中,然后释放同步状态,唤醒同步队列中的后继节点,然后当前线程会进入等待状态。

当等待队列中的节点被唤醒,则唤醒节点的线程开始尝试获取同步状态。如果不是通过其他线程调用Condition.signal()方法唤醒,而是对等待线程进行中断,则会抛出InterruptedException。

如果从队列的角度去看,当前线程加入Condition的等待队列,该过程如下图示。

ここに画像を挿入説明
如图所示,同步队列的首节点并不会直接加入等待队列,而是通过addConditionWaiter()方法把当前线程构造成一个新的节点并将其加入等待队列中。

通知

调用Condition的signal()方法,将会唤醒在等待队列中等待时间最长的节点(首节点),在唤醒节点之前,会将节点移到同步队列中。

== ConditionObject的signal方法:==
ここに画像を挿入説明
调用该方法的前置条件是当前线程必须获取了锁,可以看到signal()方法进行了isHeldExclusively()检查,也就是当前线程必须是获取了锁的线程。接着获取等待队列的首节点,将其移动到同步队列并使用LockSupport唤醒节点中的线程。

下に示すように、キューの同期にプロセス待ちキューからノード:
ここに画像を挿入説明

ENQ(ノードノード)メソッドを移動させることにより、シンクロ安全に同期キューへの呼び出しを待っているヘッドノードのスレッドキュー。同期キューにすると、ノードが移動し、スレッドウェイクLockSupportノードを使用して、現在のスレッド。

スレッドがウェイクアップした後()メソッド出口循環しながら待つであろう(真isOnSyncQueue(ノードノード)メソッド戻り、ノードが同期待ち行列にすでにある)、次にacquireQueued同期呼び出し()メソッドは、同期ステータスを得るために添加され競争。

正常同期状態(またはロック)を取得した後に、前コールのawait()メソッドの戻りから復帰するスレッド、この時間は、スレッドが正常にロックを獲得しました。

signalAllの条件()メソッドは、各ノードがキューで待機することと等価である信号()メソッドの実装であり、効果は、すべての同期キューを移動するために、キュー内のすべてのノードを待ち、各ノード対のスレッドを起動することです。

公開された635元の記事 ウォンの賞賛1857 ビュー23万+

おすすめ

転載: blog.csdn.net/cold___play/article/details/104055654