ReentranLock
是一個支持重入的獨佔鎖,在java.util.concurrent
包中,底層就是基於AQS
實現的,因此下面會設計到AQS的一些東西,若是還不瞭解的能夠先看這篇 Java AQS底層原理解析 瞭解一下。java
Sync類segmentfault
在源碼中能夠看到ReentrantLock
類自己並無繼承AQS
,而是建立了一個內部類Sync
來繼承AQS
,而ReentrantLock
類自己的那些方法都是調用Sync
裏面的方法來實現,而Sync
自己本身也是一個抽象類,它還有兩個子類,分別是NonfairSync
和FairSync
,對鎖各類實際的實現其實在這兩個類中實現,顧名思義,這兩個類分別實現了非公平鎖和公平鎖,在建立ReentrantLock
時能夠進行選擇。函數
// 默認構造函數是建立一個非公平鎖 public ReentrantLock() { sync = new NonfairSync(); } // 接受一個boolean參數,true是建立公平鎖,false是非公平鎖 public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
lock()ui
會調用Sync類中的lock()方法,因此須要看建立的是公平鎖仍是非公平鎖this
public void lock() { sync.lock(); }
非公平鎖中的lock()
方法,先試用CAS
的方式更新AQS
中的state
的狀態,默認是0表明沒有被獲取,當前線程就能夠獲取鎖,而後把state
改成1,接着把當前線程標記爲持有鎖的線程,若是if
中的操做失敗就表示鎖已經被持有了,就會調用acquire()
方法線程
final void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); }
acquire()
方法是AQS
中的那個方法,這裏面調用子類實現的tryAcquire()
方法,最終是調用到Sync
類中的nonfairTryAcquire()
方法,能夠看到先判斷state
是否是0,也就是能不能獲取鎖,若是不能則判斷請求鎖的線程和持有鎖的是否是同一個,若是是的話就把state
的值加1,也就是實現了重入鎖設計
public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); } protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; }
重寫的tryAcquire()
方法,上面非公平鎖是調用的Sync
裏的tryAcquire()
方法,而公平鎖則在子類NonfairSync
中重寫了這個方法,注意if(c==0)
判斷中的代碼,也就是線程搶奪鎖的時候會調用hasQueuedPredecessors()
方法,這個方法會判斷隊列中有沒有已經先等待的線程了,若是有則當前線程不會搶到鎖,這就實現了公平性,上面nonfairTryAcquire()
方法則沒有這種判斷,因此後來的線程可能會比先等待的線程先拿到鎖code
protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } public final boolean hasQueuedPredecessors() { // The correctness of this depends on head being initialized // before tail and on head.next being accurate if the current // thread is first in queue. Node t = tail; // Read fields in reverse initialization order Node h = head; Node s; return h != t && ((s = h.next) == null || s.thread != Thread.currentThread()); }
tryLock()繼承
這個方法是嘗試去獲取鎖,若是成功返回true
,失敗則返回false
。會發現調用的就是上面Sync
中的nonfairTryAcquire()
方法隊列
public boolean tryLock() { return sync.nonfairTryAcquire(1); }
unlock()
這個方法是釋放鎖,最終會調用到Sync
類中的tryRelease()
方法。在這個方法裏面會對state
減1,若是減1以後爲0就表示當前線程持有次數完全清空了,須要釋放鎖
public void unlock() { sync.release(1); } public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; } protected final boolean tryRelease(int releases) { int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free; }
若是看了 Java AQS底層原理解析 這篇文章,就會發現其實JUC
中的不少鎖都是在AQS
的基礎上實現的,並且最複雜的邏輯也是在AQS
中實現的,這些鎖只是在它的基礎上實現本身的需求。