摘要:關于接口的介紹,可以參見多線程進階二鎖框架接口。最終線程釋放了鎖,并進入阻塞狀態。當線程被通知喚醒時,則是將條件隊列中的結點轉換成等待隊列中的結點,之后的處理就和獨占功能完全一樣。
本文首發于一世流云的專欄:https://segmentfault.com/blog...一、本章概述
本章將繼續以ReentrantLock的調用為例,說明AbstractQueuedSynchronizer提供的Conditon等待功能。關于Conditon接口的介紹,可以參見:Java多線程進階(二)—— juc-locks鎖框架:接口。
二、Condition接口的實現J.U.C包提供了Conditon接口,用以對原生的Object.wait()、Object.notify()進行增強。
Condition接口的實現類其實是在AQS中——ConditionObject,ReentranLock的newConditon方法其實是創建了一個AbstractQueuedSynchronizer.ConditionObject對象:
Condition作為AQS的內部類,復用了AQS的結點,維護一個條件隊列,隊列初始時的結構如下:
假設現在有3個線程:ThreadA、ThreadB、ThreadC,一個Conditon實現對象。
ReentrantLock lock = new ReentrantLock();
Conditon con = lock.newConditon();
線程將以以下的時序調用:
//ThreadA先調用lock方法獲取到鎖,然后調用con.await() //ThreadB獲取鎖,調用con.signal()喚醒ThreadA //ThreadB釋放鎖1. ThreadA獲取到鎖后,首先調用await方法
上述方法,先對線程中斷做一次預判斷,然后將線程包裝成結點插入【條件隊列】,插入完成后,條件隊列的結構如下:
我們知道,await()方法會釋放當前線程持有的鎖,這個過程其實就是fullyRelease方法的作用:
然后,判斷當前結點是不是在【等待隊列】中,不在的話就會阻塞線程。
最終線程A釋放了鎖,并進入阻塞狀態。
由于Condition的signal方法要求線程必須獲得與此Condition對象相關聯的鎖,所以這里有個中斷判斷:
然后,會調用doSignal方法,刪除條件隊列中的隊首CONDITION類型結點:
刪除完成后,transferForSignal方法會將CONDITON結點轉換為初始結點,并插入【等待隊列】:
此時,【條件隊列】已經空了:
而ThreadA被包裝成新結點后,插入【等待隊列】:
終于ThreadB釋放了鎖,釋放成功后,會調用unparkSuccessor方法(參加AQS獨占功能的講解),喚醒隊列中的首結點:
最終等待隊列結構如下:
ThreadA被喚醒后,從await方法的阻塞處開始繼續往下執行:
之后會調用acquireQueued方法再次嘗試獲取鎖,獲取成功后,最終等待隊列狀態如下:
三、總結本章以ReentrantLock的公平鎖為例,分析了AbstractQueuedSynchronizer的Condition功能。
通過分析,可以看到,當線程在指定Condition對象上等待的時候,其實就是將線程包裝成結點,加入了條件隊列,然后阻塞。當線程被通知喚醒時,則是將條件隊列中的結點轉換成等待隊列中的結點,之后的處理就和獨占功能完全一樣。
除此之外,Condition還支持限時等待、非中斷等待等功能,分析思路是一樣的,讀者可以自己去閱讀AQS的源碼,通過使用示例,加入調試斷點一步步看內部的調用流程,主干理順了之后,再看其它分支,其實是異曲同工的。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/76553.html
摘要:二接口簡介可以看做是類的方法的替代品,與配合使用。當線程執行對象的方法時,當前線程會立即釋放鎖,并進入對象的等待區,等待其它線程喚醒或中斷。 showImg(https://segmentfault.com/img/remote/1460000016012601); 本文首發于一世流云的專欄:https://segmentfault.com/blog... 本系列文章中所說的juc-...
摘要:開始獲取鎖終于輪到出場了,的調用過程和完全一樣,同樣拿不到鎖,然后加入到等待隊列隊尾然后,在阻塞前需要把前驅結點的狀態置為,以確保將來可以被喚醒至此,的執行也暫告一段落了安心得在等待隊列中睡覺。 showImg(https://segmentfault.com/img/remote/1460000016012467); 本文首發于一世流云的專欄:https://segmentfault...
摘要:好了,繼續向下執行,嘗試獲取鎖失敗后,會調用首先通過方法,將包裝成共享結點,插入等待隊列,插入完成后隊列結構如下然后會進入自旋操作,先嘗試獲取一次鎖,顯然此時是獲取失敗的主線程還未調用,同步狀態還是。 showImg(https://segmentfault.com/img/remote/1460000016012541); 本文首發于一世流云的專欄:https://segmentfa...
摘要:關于,最后有兩點規律需要注意當的等待隊列隊首結點是共享結點,說明當前寫鎖被占用,當寫鎖釋放時,會以傳播的方式喚醒頭結點之后緊鄰的各個共享結點。當的等待隊列隊首結點是獨占結點,說明當前讀鎖被使用,當讀鎖釋放歸零后,會喚醒隊首的獨占結點。 showImg(https://segmentfault.com/img/remote/1460000016012293); 本文首發于一世流云的專欄:...
摘要:公平策略在多個線程爭用鎖的情況下,公平策略傾向于將訪問權授予等待時間最長的線程。使用方式的典型調用方式如下二類原理的源碼非常簡單,它通過內部類實現了框架,接口的實現僅僅是對的的簡單封裝,參見原理多線程進階七鎖框架獨占功能剖析 showImg(https://segmentfault.com/img/remote/1460000016012582); 本文首發于一世流云的專欄:https...
閱讀 1978·2019-08-30 15:54
閱讀 3602·2019-08-29 13:07
閱讀 3129·2019-08-29 12:39
閱讀 1793·2019-08-26 12:13
閱讀 1552·2019-08-23 18:31
閱讀 2164·2019-08-23 18:05
閱讀 1852·2019-08-23 18:00
閱讀 1048·2019-08-23 17:15