深入ReentrantLock原始碼解析
阿新 • • 發佈:2019-01-27
ReentrantLock是基於AQS實現的,它提供了公平鎖與非公平鎖兩種策略,當然這兩種策略都是搶佔式的。其核心程式碼是對AQS的公平、非公平的實現,下面我們來看其核心程式碼:
內部類Sync,該類定義為抽象類,並繼承自AbstractQueuedSynchronizer,它還會被NonfairSync(非公平策略)與FairSync(公平策略)兩個類繼承。主要關注nonfairTryAcquire方法與tryRelease方法
// Sync類繼承自AbstractQueuedSynchronizer, abstract static class Sync extends
NonfairSync,繼承自Sync,非公平鎖策略,實現很簡單,因為Sync已經都實現了非公平的策略
static final class NonfairSync extends Sync { private static final long serialVersionUID = 7316153563782823691L; /** * 實現lock方法。先通過compareAndSetState嘗試獲取一次,如果成功則獲取鎖。 * 否則走acquire,詳見AbstractQueuedSynchronizer原始碼解析。 */ final void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); } // 重寫tryAcquire,直接呼叫Sync的nonfairTryAcquire方法。 protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } }
FairSync,繼承自Sync,公平策略。需要實現公平策略的tryAcquire
static final class FairSync extends Sync { private static final long serialVersionUID = -3000897897090466540L; // 區別1:這裡沒有先嚐試獲取一次,因為公平模式必須要排隊。而非公平模式不用考慮佇列,所以可以先使用compareAndSetState獲取一次 final void lock() { acquire(1); } /** * 公平鎖策略 */ protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { // 主要區別在這裡,在競爭之前,先判斷!hasQueuedPredecessors() // 如果當前執行緒在隊首,則hasQueuedPredecessors返回false 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; } }