說明:以下內容皆屬于個人對源碼的理解楣富,可能存在歧義奕谭、誤解、錯誤及理解不全面的情況尝蠕,還望指正
一、ReentrantLock介紹
ReentrantLock類是JDK1.5版本后出現(xiàn)的類载庭,這個類有什么作用看彼,能用來干嘛呢?首先看看Dog李對它的描述:ReentrantLock具有:與使用synchronized關鍵字的方法和語句的隱式監(jiān)視鎖相同的基本行為與語義囚聚,但是它也是具有可擴展的可重入的互斥鎖闲昭。
是不是一口氣理解不了?外國人說話就是費勁靡挥,注釋就不能一點一點的說明序矩,非得一口氣說完。大概意思就是ReentrantLock與synchronized實現(xiàn)的功能一樣跋破,但是ReentrantLock是可擴展的簸淀。
ReentrantLock對象鎖是被最后一次鎖定且尚未釋放鎖的線程所擁有,當一個線程調用lock()方法時毒返,如果鎖沒有被其它線程鎖擁有租幕,那么該線程將會獲得鎖,并且立即返回成功拧簸。如果該線程已擁有鎖劲绪,那么會將持有鎖的數(shù)量加1。通過ReentrantLock的isHeldByCurrentThread()方法或者getHoldCount()方法可以判斷線程是否已獲得鎖盆赤。
二贾富、內部lock()方法實現(xiàn)
首先介紹一下ReentrantLock中定義的三個內部類:Sync、NonfairSync和FairSync牺六。ReentrantLock中的lock()方法便是由Sync中定義的抽象方法lock()方法實現(xiàn)的颤枪。NonfairSync和FairSync分別繼承Sync,實現(xiàn)了具體的lock()方法淑际。源碼就不拷貝了畏纲,只做類的作用及lock()方法的描述:
-
Sync
鎖同步控制的基礎類扇住,子類分為公平與非公平鎖。使用AQS(就是Sync的父類AbstractQueuedSynchronizer)狀態(tài)來表示鎖的持有數(shù)量盗胀。此外Sync內部還提供了釋放鎖艘蹋、獲取當前持有鎖的Thread對象等方法。 -
FairSync
FairSync重寫了AQS的tryAcquire()方法票灰,因此在請求獲取鎖的實現(xiàn)上作了調整簿训,在請求獲取鎖時首先判斷AQS狀態(tài)(鎖的持有數(shù)量)是否為0。若為0:判斷請求隊列中該線程之前是否沒有在排隊的線程且是可以獲取鎖的狀態(tài)米间,滿足條件則將當前線程設為鎖的持有者强品。否則返回false。若不為0:則判斷鎖的持有者是否為當前線程屈糊。如果不是的榛,返回false。 -
NonfairSync
首先根據(jù)CAS返回結果判斷是否可以獲取鎖逻锐,如果可以夫晌,則直接將當前線程設為鎖的持有者,否則中斷自己身執(zhí)行狀態(tài)昧诱,加入請求隊列獲取鎖直到獲取成功晓淀。
在實際應用中,具體使用哪種獲取鎖的方式可以在創(chuàng)建ReentrantLock類的實例時決定盏档。ReentrantLock中有兩個構造函數(shù)凶掰,一個是默認的構造函數(shù),一個是帶boolean參數(shù)的構造函數(shù)蜈亩。參數(shù)為true懦窘,表示使用公平鎖的方式,false為非公平鎖的方式稚配。ReentrantLock默認創(chuàng)建的是NonfairSync對象畅涂,因此獲取鎖時調用的也就是NonfairSync對象的lock()方法。
從上面的三個內部類可以了解到道川,非公平鎖的方式明顯比公平鎖的方式獲取鎖的速度要快(單線程下影響可以忽略不計)午衰,因此效率也比公平鎖的方式效率要高。ReentrantLock還提供了其它的獲取鎖的方式冒萄,所以在具體使用哪種方式獲取鎖可視情況而定臊岸。
三、其它方法
ReentrantLock還提供了lockInterruptibly()(中斷方式獲取鎖)宦言、tryLock()(無參和有參兩個方法扇单,無參方法類似于非公平方式鎖的lock()方法商模,前提條件是在鎖未被其它線程持有的情況下奠旺。如果鎖被其它線程持有蜘澜,則不會加入隊列等待獲取鎖,而是立即返回false响疚。帶參數(shù)的表示在指定時間內且當前線程未中斷的情況)及其它如釋放鎖鄙信、獲取鎖持有數(shù)量等方法。源碼忿晕、文檔看一下特別清晰装诡,就不單獨列舉說明了。