看了下J.U.C併發包下的ReentrantLock源碼,費了很多勁,作個小總結吧,儘可能用通俗易懂的語言描述,配上一些圖說明。java
ReentrantLock介紹編程
ReentrantLock是基於AbstractQueuedSynchronizer(AQS框架)設計的,類裏面有一個私有sync成員屬性,其類型爲AbstractQueuedSynchronizer;併發
那麼什麼是AQS框架呢?AQS是由大神Doug Lea設計的,他寫了一篇論文叫《The java.util.concurrent Synchronizer Framework 》,裏面詳細描述了AQS的設計思想,想看中文翻譯的,能夠去併發編程網裏閱讀,連接。框架
我這裏簡要說明下,AQS主要是維護了一個int類型的state屬性,一個非阻塞、先進先出的線程等待隊列;其中state是用volatile修飾的,保證線程之間的可見性,隊列的入隊和出對操做都是無鎖操做,基於自旋鎖和CAS實現;另外AQS分爲兩種模式:獨佔模式和共享模式,本文討論的ReentrantLock,主要涉及AQS的獨佔模式;源碼分析
回過頭來講ReentrantLock,其內部有三個內部類Sync、NonfairSync和FairSync,其中NonfairSync和FairSync繼承Sync,Sync繼承AbstractQueuedSynchronizer,這三個內部類主要是爲了實現父類AbstractQueuedSynchronizer中未實現的tryRelease(int)和tryAcquire(int)方法;ui
其實ReentrantLock類自己並無實現什麼新功能,仔細觀察其下面的方法,發現都是經過調用sync的方法去實現的,以下所示:spa
//省略前面部分... public boolean tryLock() { return sync.nonfairTryAcquire(1); } public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(timeout)); } public void unlock() { sync.release(1); } public Condition newCondition() { return sync.newCondition(); } public boolean isHeldByCurrentThread() { return sync.isHeldExclusively(); } //省略後面部分...
源碼分析線程
先看一下咱們平時都是怎樣使用ReentrantLock的,以下代碼:翻譯
ReentrantLock lock = new ReentrantLock(); lock.lock(); try { // do something } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); }
這裏的ReentrantLock是一個非公平獨佔鎖,其保證do something在同一時刻只有一個線程能訪問,當有線程正在執行do something裏的代碼時,其它線程將會等待。設計
那麼,咱們就先從lock方法開始,分析ReentrantLock是如何實現非公平獨佔鎖的;
ReentrantLock的lock方法調用的是sync的lock方法,而sync是在構造方法裏初始化的,因爲咱們未傳入參數,默認爲NonfairSync類型;
lock方法,調用sync的lock方法:
public void lock() { sync.lock(); }
無參構造方法,默認爲非公平鎖:
public ReentrantLock() { sync = new NonfairSync(); }
按照執行步驟,轉到NonfairSync的lock方法:
接着調用: