公平鎖與非公平鎖是指,多個線程在獲取同一把鎖的策略,是按照先到先得仍是直接競爭。先到先得的策略就是公平鎖,排隊對全部的線程來講是公平的,直接競爭的策略則是非公平的。java
在調用ReenterantLock的構造函數的時候決定是構造一個公平鎖仍是非公平鎖。node
public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
來看獲取鎖的過程:函數
ReentrantLock lock = new ReentrantLock(); lock.lock();
點進去看,是調用了sync的lock方法
這裏就是對應了咱們的公平鎖/非公平鎖的lock方法。
到這裏沒有什麼大的差別,無非是非公平鎖多了一個步驟。cas操做去嘗試獲取鎖,成功了設置owner線程爲當前線程。失敗了再調用acquire方法獲取鎖。
那接下來繼續看兩種鎖的acquire方法,兩個方法都來到了aqs的acquire方法。ui
點進去那些方法,全部方法都進入了aqs實現的步驟,只有tryAcquire方法有不一樣的實現。
進去看,公平鎖只是多了 hasQueuedPredecessors
這個方法。spa
公平鎖線程
protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { // 當前鎖的狀態是無所狀態 if (!hasQueuedPredecessors() && // 判斷隊列中是否有前驅節點,若果有前驅節點,就不會執行下面的代碼,不會去獲取鎖 compareAndSetState(0, acquires)) { // 使用cas嘗試獲取鎖 setExclusiveOwnerThread(current); // 設置owner線程爲當前線程 return true; } } else if (current == getExclusiveOwnerThread()) { // 持有鎖的線程爲當前線程 int nextc = c + acquires; if (nextc < 0) throw new Error("Maximum lock count exceeded"); setState(nextc); // 更新sate(重入鎖的原理) return true; } return false; }
以上分析了公平鎖和非公平鎖的一個不一樣。
下面以非公平鎖分析加鎖的過程
獲取鎖的過程:code
/** * Performs lock. Try immediate barge, backing up to normal * acquire on failure. */final void lock() { if (compareAndSetState(0, 1)) // 嘗試用cas來獲取鎖(改變state的值) setExclusiveOwnerThread(Thread.currentThread()); // 設置owner線程爲當前線程 else acquire(1); // 若是鎖的狀態不爲0,被其餘線程持有,嘗試獲取鎖 }
public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
tryAcquire(arg)方法是嘗試獲取鎖。orm
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方法一致。隊列
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
方法:
addWaiter方法:get
private Node addWaiter(Node mode) { Node node = new Node(Thread.currentThread(), mode); // Try the fast path of enq; backup to full enq on failure Node pred = tail; if (pred != null) { node.prev = pred; if (compareAndSetTail(pred, node)) { pred.next = node; return node; } } enq(node); return node; }
建立一個node,入隊,並返回該NodeacquireQueued
再嘗試獲取鎖
非公平鎖解鎖的過程:
public final boolean release(int arg) { if (tryRelease(arg)) { // 嘗試去釋放鎖 Node h = head; if (h != null && h.waitStatus != 0) // h頭結點爲空,而且state不等於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); // 設置owner線程爲空 } setState(c); // 更新state return free; }