在上一節中,描述了Lock包的核心基礎–AQS,本節將講述其具體實現:ReentrantLock,ReentrantReadWriteLock。在這之前先說一下必要定義。
可重入鎖:已在syn章節提及過,此處詳細描述。某個線程獲取到鎖之後,在未釋放鎖之前的時間內,當需要獲取鎖時不需要獲取鎖的操作,可直接拿到資源。
公平鎖:通俗的說,就是先等待的線程先獲得鎖。
非公平鎖:與公平鎖相反,每次需要獲取鎖時大家一起競爭,並不是先到先得。鎖。
一、ReentrantLock
ReentrantLock是可重入鎖,獨佔鎖,實現Lock接口,內部實現了公平鎖與非公平鎖兩種鎖形式,默認使用非公平鎖。
一、屬性
private final Sync sync;
該類有屬性Sync,用final修飾即初始化之後不可更改,Sync是AQS的一個子類,有兩個子類NonfairSync與FairSync,分別用於實現非公平鎖與公平鎖。
二、靜態內部類
接下來是靜態內部類,這裏使用靜態內部類便是爲了讓這些類中的方法都只讓ReentrantLock使用。
1.Sync
該類是AQS的子類,重寫了一些方法(AQS需要實現,公平鎖與非公平鎖通用),是NonfairSync與FairSync的父類。
接下如acquire(),tryAcquire(),release()等屬於AQS類的重要方法,在上一篇描述AQS的blog中已經詳細闡述,此處不再闡述。
abstract static class Sync extends AbstractQueuedSynchronizer {
abstract void lock();
//不公平獲取鎖
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;
}
//嘗試釋放鎖
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;
}
//是否擁有當前鎖
protected final boolean isHeldExclusively() {
return getExclusiveOwnerThread() == Thread.currentThread();
}
//獲取一個條件隊列
final ConditionObject newCondition() {
return new ConditionObject();
}
//獲取佔有鎖的線程
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
//獲取該線程佔有多少資源
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
//資源是否被搶佔
final boolean isLocked() {
return getState() != 0;
}
}
上述代碼實現都比較簡單,根據註釋就能瞭解,不再分析。
2.NonfairSync
該類是Sync的實現類,是不公平鎖的實現。在ReentrantLock中使用的
static final class NonfairSync extends Sync {
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
上述代碼有兩方法:
lock():獲取獨佔鎖,若未獲取則將線程阻塞等待。實現較簡單:使用CAS將state從0置爲1,若成功則代表獲取資源成功;若失敗則調用acquire()進行操作。
tryAcquire():獲取鎖,此處是直接調用父類Sync的nonfairTryAcquire方法。
疑問:nonfairTryAcquire()方法是不公平的獲取鎖,爲什麼要置於父類中,而不是子類NonfairSync中?
解答:通過跟蹤源碼,發現nonfairTryAcquire方法除了此處還有一處調用,在ReentrantLock對外提供的tryLock()方法中,用於立刻獲取獨佔鎖。故若將該方法放入子類NonfairSync中,則公平鎖無法提供此功能。而對於我們來說,即使我們實現的是公平鎖,在某些時刻也需要此功能。
3.FairSync
該類是Sync的實現類,是公平鎖的實現。在ReentrantLock中使用的
static final class FairSync extends Sync {
final void lock() {
acquire(1);
}
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;
}
}
上述代碼有兩方法:
lock():獲取獨佔鎖,直接調用acquire()進行操作。
tryAcquire():獲取鎖。
4.總結
通過上述公平鎖與非公平鎖的實現,其區別在於:
- lock():獲取獨佔鎖,公平鎖時直接調用acquire(1),將該線程放入隊尾,等待獲取;而非公平鎖則是先直接獲取鎖(無論CLH隊列中是否有其他線程在等待),失敗纔會將該線程放入隊尾。
- tryAcquire():嘗試獲取鎖,其實此方法只是獲取鎖過程中的一部分。其區別在於可以獲取鎖時,公平鎖的處理是
!hasQueuedPredecessors() &&compareAndSetState(0, acquires)
,需要在隊列前面沒有其他等待線程纔會嘗試獲取鎖;而非公平鎖的處理是compareAndSetState(0, acquires)
,無論是否有其他線程,直接嘗試獲取鎖。
三、構造器
ReentrantLock對外提供兩個構造器:
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
- ReentrantLock(),默認構造器,默認使用非公平鎖,故上文中描述該類默認使用非公平鎖
- ReentrantLock(boolean fair),帶參構造器,傳入true則是公平鎖,false是非公平鎖
四、對外提供方法
ReentrantLock提供了一系列方法,都是基於AQS以及上述Sync系列靜態內部類實現,實現原理較簡單,作用見註釋,不一一詳述。
//獲取鎖,若未獲取則將線程阻塞等待
public void lock() {
sync.lock();
}
//獲取鎖。若未獲取則將線程阻塞等待,直到獲取鎖。如果有中斷請求就會產生中斷異常
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
//立刻嘗試獲取鎖
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
//立刻嘗試在指定時間內獲取鎖,直接調用AQS中方法
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 int getHoldCount() {
return sync.getHoldCount();
}
//是否是當前線程佔有鎖
public boolean isHeldByCurrentThread() {
return sync.isHeldExclusively();
}
//鎖是否被持有
public boolean isLocked() {
return sync.isLocked();
}
//是否是公平鎖
public final boolean isFair() {
return sync instanceof FairSync;
}
//獲取持有鎖的線程
protected Thread getOwner() {
return sync.getOwner();
}
//是否有線程等待獲取鎖
public final boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
}
//CLH隊列長度
public final int getQueueLength() {
return sync.getQueueLength();
}
//獲取所有正在等待獲取鎖的線程,返回是list<Thread>
protected Collection<Thread> getQueuedThreads() {
return sync.getQueuedThreads();
}
//等待隊列中是否有等待線程
public boolean hasWaiters(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
}
//等待隊列中的線程數
public int getWaitQueueLength(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
}
//獲取所有等待隊列中的線程,返回是list<Thread>
protected Collection<Thread> getWaitingThreads(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
}
一、ReentrantReadWriteLock
ReentrantReadWriteLock是可重入鎖。裏面有兩把鎖,讀鎖與寫鎖,其中讀鎖採用共享鎖,寫鎖採用獨佔鎖。不能同時存在讀鎖與寫鎖。內部實現了公平鎖與非公平鎖兩種鎖形式,默認使用非公平鎖。
寫線程雖然一次只有一個訪問數據,但讀線程可以同時讀取,而在實際中,讀取往往都是大量的,寫入是偶爾的,讀-寫鎖利用了這一點。從理論上講,與互斥鎖相比,使用讀-寫鎖所允許的併發性增強將帶來更大的性能提高。在實踐中,只有在多處理器上並且只在訪問模式適用於共享數據時,才能完全實現併發性增強。
讀寫鎖不能同時存在。
一、屬性
private final ReentrantReadWriteLock.ReadLock readerLock;
private final ReentrantReadWriteLock.WriteLock writerLock;
final Sync sync;
該類有屬性Sync,readerLock,writerLock,均用final修飾即初始化之後不可更改,Sync是AQS的一個子類,有兩個子類NonfairSync與FairSync,分別用於實現非公平鎖與公平鎖。readerLock爲讀鎖,writerLock爲寫鎖
二、靜態內部類
接下來是靜態內部類,這裏使用靜態內部類便是爲了讓這些類中的方法都只讓ReentrantLock使用。
1.Sync
該類是AQS的子類,重寫了一些方法(AQS需要實現,公平鎖與非公平鎖通用),是NonfairSync與FairSync的父類。
接下如acquire(),tryAcquire(),release()等屬於AQS類的重要方法,在上一篇描述AQS的blog中已經詳細闡述,此處不再闡述。
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 6317671515068378041L;
/*
* 鎖狀態state是int型,讀寫分爲兩部分,各用一個無符號short來表示
* 低位的表示寫鎖即獨享鎖,高位的表示讀鎖共享數
*/
// 這個16是兩個字節,一個short的長度
static final int SHARED_SHIFT = 16;
// 1左移16位,爲00000000 00000001 00000000 00000000
static final int SHARED_UNIT = (1 << SHARED_SHIFT);
// 1左移16位,減1,爲65535,讀寫的獲取鎖的最大次數
static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
// 右移16位,獲取c高位的16位,表示讀鎖的共享總數(高位2字節全0)
static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
// 和兩個字節的全1字節與操作,高位2字節全0,獲取寫鎖的總數
static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
// 每個線程的計數器,保存讀鎖共享數
static final class HoldCounter {
int count = 0;
final long tid = getThreadId(Thread.currentThread());
}
// ThreadLocal的子類
static final class ThreadLocalHoldCounter
extends ThreadLocal<HoldCounter> {
// 初始化方法,返回HoldCounter
public HoldCounter initialValue() {
return new HoldCounter();
}
}
// 讀線程的一個集合,但不包括最後一個讀線程和第一個讀線程
private transient ThreadLocalHoldCounter readHolds;
// 最後一個讀線程的計數
private transient HoldCounter cachedHoldCounter;
// 第一個讀線程
private transient Thread firstReader = null;
// 第一個讀線程的計數
private transient int firstReaderHoldCount;
Sync() {
readHolds = new ThreadLocalHoldCounter();
setState(getState()); // ensures visibility of readHolds
}
// 讀鎖的阻塞
abstract boolean readerShouldBlock();
// 寫鎖的阻塞
abstract boolean writerShouldBlock();
// 釋放寫鎖
protected final boolean tryRelease(int releases) {
if (!isHeldExclusively())
// 當前線程不是owner線程,不能進行釋放
throw new IllegalMonitorStateException();
// 計算釋放後的狀態值
int nextc = getState() - releases;
// 如果當前寫鎖釋放後,看是否還有寫鎖,沒有寫鎖返回true
boolean free = exclusiveCount(nextc) == 0;
if (free)
// 沒有寫鎖了將鎖對象的當前owner置爲null
setExclusiveOwnerThread(null);
// 更新state的新值
setState(nextc);
return free;
}
// 嘗試獲取寫鎖
protected final boolean tryAcquire(int acquires) {
// 當前線程
Thread current = Thread.currentThread();
// 狀態c,包含讀鎖和寫鎖的總數
int c = getState();
// w表示寫鎖的總數
int w = exclusiveCount(c);
if (c != 0) {
// 如果寫鎖爲0,說明當前有讀鎖(也可能是當前線程有讀鎖),不能獲取寫鎖
// 如果寫鎖不爲0,但是當前線程不是owner線程不可重入,不能獲取寫鎖
if (w == 0 || current != getExclusiveOwnerThread())
return false;
// 寫鎖數量超過了65535報錯
if (w + exclusiveCount(acquires) > MAX_COUNT)
throw new Error("Maximum lock count exceeded");
// 這裏已經說明寫鎖是當前線程可重入的了,直接設置state值,返回true
setState(c + acquires);
return true;
}
// c==0時,如果寫需要阻塞或者設置狀態失敗,返回false
if (writerShouldBlock() ||
!compareAndSetState(c, c + acquires))
return false;
// 設置鎖的owner獨佔標識
setExclusiveOwnerThread(current);
return true;
}
// 嘗試釋放讀鎖
protected final boolean tryReleaseShared(int unused) {
// 當前線程current
Thread current = Thread.currentThread();
// 如果當前線程是第一個獲取讀鎖的
if (firstReader == current) {
// 當前線程讀鎖總數爲1,直接將firstReader置爲null
if (firstReaderHoldCount == 1)
firstReader = null;
// 如果不爲1,那麼減掉1即可
else
firstReaderHoldCount--;
} else {
// 最後一個獲取讀鎖的線程
HoldCounter rh = cachedHoldCounter;
// 如果當前線程也不是最後一個獲取讀鎖的線程,從ThreadLocal中取
if (rh == null || rh.tid != getThreadId(current))
rh = readHolds.get();
// 當前線程讀鎖的個數
int count = rh.count;
// 如果count==1,釋放了就爲0,直接在ThreadLocal中去掉當前線程
if (count <= 1) {
readHolds.remove();
// count<=0,此時拋出不匹配釋放鎖的異常
if (count <= 0)
throw unmatchedUnlockException();
}
// 正常情況下,將當前線程的讀鎖count值減1即可。
--rh.count;
}
for (;;) {
int c = getState();
// 高位減1,新的讀寫鎖值
int nextc = c - SHARED_UNIT;
// 嘗試設置state值,預測之前爲c,更新爲nextc
if (compareAndSetState(c, nextc))
// 釋放讀鎖不會影響其他讀鎖,但是如果這時讀寫鎖都空閒,等待中的寫線程將開始執行
// 這裏只有讀寫鎖都釋放了,才返回true
return nextc == 0;
}
}
// 釋放讀鎖的不匹配異常
private IllegalMonitorStateException unmatchedUnlockException() {
return new IllegalMonitorStateException(
"attempt to unlock read lock, not locked by current thread");
}
// 嘗試獲取讀鎖
protected final int tryAcquireShared(int unused) {
// 當前線程
Thread current = Thread.currentThread();
// 鎖的state值
int c = getState();
// 如果有獨佔標識同時當前線程並不是獨佔線程時,直接返回-1
if (exclusiveCount(c) != 0 &&
getExclusiveOwnerThread() != current)
return -1;
// 讀鎖的總數
int r = sharedCount(c);
// 如果讀不需要阻塞,同時讀鎖小於65535,並且能夠CAS設置c的值讀個數加1
// 這裏的阻塞策略readerShouldBlock進行了判斷,有兩種情況:
// 1.公平模式:如果AQS隊列前面有等待的結點,當前線程應該阻塞
// 2.非公平模式:如果AQS前面有線程在等待寫鎖,當前線程應該阻塞(這樣做的原因是爲了防止寫飢餓)。
// 出現這個阻塞情況,就不走下邊的if了,直接到最後走fullTryAcquireShared方法處理
if (!readerShouldBlock() &&
r < MAX_COUNT &&
compareAndSetState(c, c + SHARED_UNIT)) {
// 讀鎖個數爲0,將當前線程作爲第一個讀線程單獨保存,不存在ThreadLocal中
if (r == 0) {
firstReader = current;
// 當前線程即第一個讀線程的讀鎖總數置爲1
firstReaderHoldCount = 1;
// 如果r!=0,說明有讀線程了,判斷當前線程是不是第一個讀線程
} else if (firstReader == current) {
// 如果當前線程就是第一個讀線程,數量count加1即可
firstReaderHoldCount++;
} else {
// 當前線程不是第一個讀線程,判斷是不是最後一個讀線程
HoldCounter rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current))
// 當前線程不是最後一個讀線程,從ThreadLocal中取線程
// 同時將最後一個讀線程更新爲當前線程
cachedHoldCounter = rh = readHolds.get();
// 這裏如果當前線程就是最後一個讀線程的話,如果count爲0
else if (rh.count == 0)
// 需要重新set當前線程(之前釋放時,readHolds.remove()進行過這個操作)
readHolds.set(rh);
// 將當前線程的count加1
rh.count++;
}
// 返回值1說明獲取讀鎖成功了
return 1;
}
// 讀線程阻塞時,執行這個方法
return fullTryAcquireShared(current);
}
// 該方法處理讀線程阻塞的情況
final int fullTryAcquireShared(Thread current) {
HoldCounter rh = null;
for (;;) {
int c = getState();
// 獨佔標記存在且當前owner不是當前線程,不能重入
if (exclusiveCount(c) != 0) {
if (getExclusiveOwnerThread() != current)
return -1;
// 沒有寫鎖存在時,如果讀阻塞
// 這裏的阻塞策略,如果:1.公平模式:如果當前AQS隊列前面有等待的結點,返回false;2.非公平模式:如果
// AQS前面有線程在等待寫鎖,返回false(這樣做的原因是爲了防止寫飢餓)。
} else if (readerShouldBlock()) {
// 如果當前線程是第一個讀線程
if (firstReader == current) {
} else {
if (rh == null) {
// 優先賦值成上一次獲取讀鎖成功的cache,即最後一個讀鎖
rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current)) {
// 如果和當前線程不匹配,從ThreadLocal中取
rh = readHolds.get();
if (rh.count == 0)
readHolds.remove();
}
}
// 不是讀鎖重入的情況,返回-1
if (rh.count == 0)
return -1;
}
}
// 如果讀鎖總數爲65535,報錯
if (sharedCount(c) == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
// 如果CAS將c的讀鎖總數增加1成功
if (compareAndSetState(c, c + SHARED_UNIT)) {
// 如果讀鎖數量爲0,當前線程作爲第一個線程存起來
if (sharedCount(c) == 0) {
firstReader = current;
firstReaderHoldCount = 1;
// 當前線程爲第一個獲取讀鎖的線程,數量加1
} else if (firstReader == current) {
firstReaderHoldCount++;
// 其他情況,和之前的方法同樣原理
} else {
if (rh == null)
rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current))
rh = readHolds.get();
else if (rh.count == 0)
readHolds.set(rh);
rh.count++;
cachedHoldCounter = rh; // cache for release
}
return 1;
}
}
}
// 和tryAcquire基本一致,去掉了考慮阻塞部分,相當於非公平模式的獲取寫鎖
final boolean tryWriteLock() {
Thread current = Thread.currentThread();
int c = getState();
if (c != 0) {
int w = exclusiveCount(c);
if (w == 0 || current != getExclusiveOwnerThread())
return false;
if (w == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
}
if (!compareAndSetState(c, c + 1))
return false;
setExclusiveOwnerThread(current);
return true;
}
// 和tryAcquireShared函數基本一致,去掉了考慮阻塞部分,相當於非公平模式的獲取讀鎖
final boolean tryReadLock() {
Thread current = Thread.currentThread();
for (;;) {
int c = getState();
if (exclusiveCount(c) != 0 &&
getExclusiveOwnerThread() != current)
return false;
int r = sharedCount(c);
if (r == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
if (compareAndSetState(c, c + SHARED_UNIT)) {
if (r == 0) {
firstReader = current;
firstReaderHoldCount = 1;
} else if (firstReader == current) {
firstReaderHoldCount++;
} else {
HoldCounter rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current))
cachedHoldCounter = rh = readHolds.get();
else if (rh.count == 0)
readHolds.set(rh);
rh.count++;
}
return true;
}
}
}
protected final boolean isHeldExclusively() {
return getExclusiveOwnerThread() == Thread.currentThread();
}
final ConditionObject newCondition() {
return new ConditionObject();
}
final Thread getOwner() {
return ((exclusiveCount(getState()) == 0) ?
null :
getExclusiveOwnerThread());
}
final int getReadLockCount() {
return sharedCount(getState());
}
final boolean isWriteLocked() {
return exclusiveCount(getState()) != 0;
}
final int getWriteHoldCount() {
return isHeldExclusively() ? exclusiveCount(getState()) : 0;
}
final int getReadHoldCount() {
if (getReadLockCount() == 0)
return 0;
Thread current = Thread.currentThread();
if (firstReader == current)
return firstReaderHoldCount;
HoldCounter rh = cachedHoldCounter;
if (rh != null && rh.tid == getThreadId(current))
return rh.count;
int count = readHolds.get().count;
if (count == 0) readHolds.remove();
return count;
}
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
readHolds = new ThreadLocalHoldCounter();
setState(0); // reset to unlocked state
}
final int getCount() { return getState(); }
}
此靜態內部類是ReentrantReadWriteLock的關鍵所在,過程已經在註釋中詳細描述,在此說明設計核心思想:
如何表示多個讀鎖與單個寫鎖 :由於state字段是32位的int,在次將state一分爲2,用高16位記錄讀鎖(共享鎖)的狀態,低16位保存寫鎖(獨佔鎖)的狀態,因此鎖的數量上限都是65535
如何表示每個讀鎖、寫鎖的重入次數:可以把線程重入讀鎖的次數作爲值存在 ThreadLocal 中
2.NonfairSync與FairSync
static final class NonfairSync extends Sync {
final boolean writerShouldBlock() {
return false; // writers can always barge
}
final boolean readerShouldBlock() {
return apparentlyFirstQueuedIsExclusive();
}
}
static final class FairSync extends Sync {
final boolean writerShouldBlock() {
return hasQueuedPredecessors();
}
final boolean readerShouldBlock() {
return hasQueuedPredecessors();
}
}
此處將公平鎖與非公平鎖放在一處,因爲大多數邏輯已經在它們的父類Sync中實現,此處各只有兩個方法:
- writerShouldBlock :寫鎖是阻塞進入等待隊列(true)還是直接獲取鎖(false)。在非公平鎖中,直接返回false;公平鎖中,若無等待線程則返回false,有等待線程返回true
- readerShouldBlock:讀鎖是阻塞進入等待隊列(true)還是直接獲取鎖(false)。在非公平鎖中,如果隊列的head.next正在等待獨佔鎖(寫鎖),則返回true,否則返回false;公平鎖中,若無等待線程則返回false,有等待線程返回true
3.ReadLock
public static class ReadLock implements Lock, java.io.Serializable {
private final Sync sync;
protected ReadLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
public void lock() {
sync.acquireShared(1);
}
public void lockInterruptibly() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
public boolean tryLock() {
return sync.tryReadLock();
}
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
public void unlock() {
sync.releaseShared(1);
}
public Condition newCondition() {
throw new UnsupportedOperationException();
}
}
內部有一屬性爲sync,是從外部類繼承過來,使用同一syn。使用共享鎖,至於方法與ReentrantLock類似,同名方法作用一樣,實現都是調用AQS以及Syn及子類方法,再次不贅述。
唯一需要注意的是,condition隊列只支持獨佔鎖,故此處不支持condition相關操作,直接拋出異常。
4.WriteLock
public static class WriteLock implements Lock, java.io.Serializable {
private final Sync sync;
protected WriteLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
//獲取鎖。若未獲取則將線程阻塞等待
public void lock() {
sync.acquire(1);
}
//獲取鎖。若未獲取則將線程阻塞等待,直到獲取鎖。如果有中斷請求就會產生中斷異常
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
//嘗試立刻獲取鎖
public boolean tryLock( ) {
return sync.tryWriteLock();
}
//嘗試立刻在指定時間內獲取鎖
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 int getHoldCount() {
return sync.getWriteHoldCount();
}
}
內部有一屬性爲sync,是從外部類繼承過來,使用同一syn。使用獨佔鎖,至於方法與ReentrantLock類似,同名方法作用一樣,實現都是調用AQS以及Syn及子類方法,再次不贅述。
三、構造器
ReentrantReadWriteLock對外提供兩個構造器:
public ReentrantReadWriteLock() {
this(false);
}
public ReentrantReadWriteLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
readerLock = new ReadLock(this);
writerLock = new WriteLock(this);
}
protected ReadLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
protected WriteLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }
public ReentrantReadWriteLock.ReadLock readLock() { return readerLock; }
- ReentrantReadWriteLock(),默認構造器,默認使用非公平鎖,故上文中描述該類默認使用非公平鎖
- ReentrantReadWriteLock(boolean fair),帶參構造器,傳入true則是公平鎖,false是非公平鎖
四、對外提供方法
ReentrantReadWriteLock提供了一系列方法,都是基於AQS以及上述Sync系列靜態內部類實現,實現原理較簡單,作用見註釋,不一一詳述。
// 返回當前擁有寫入鎖的線程,如果沒有這樣的線程,則返回 null。
protected Thread getOwner()
// 返回一個 collection,它包含可能正在等待獲取讀取鎖的線程。
protected Collection<Thread> getQueuedReaderThreads()
// 返回一個 collection,它包含可能正在等待獲取讀取或寫入鎖的線程。
protected Collection<Thread> getQueuedThreads()
// 返回一個 collection,它包含可能正在等待獲取寫入鎖的線程。
protected Collection<Thread> getQueuedWriterThreads()
// 返回等待獲取讀取或寫入鎖的線程估計數目。
int getQueueLength()
// 查詢當前線程在此鎖上保持的重入讀取鎖數量。
int getReadHoldCount()
// 查詢爲此鎖保持的讀取鎖數量。
int getReadLockCount()
// 返回一個 collection,它包含可能正在等待與寫入鎖相關的給定條件的那些線程。
protected Collection<Thread> getWaitingThreads(Condition condition)
// 返回正等待與寫入鎖相關的給定條件的線程估計數目。
int getWaitQueueLength(Condition condition)
// 查詢當前線程在此鎖上保持的重入寫入鎖數量。
int getWriteHoldCount()
// 查詢是否給定線程正在等待獲取讀取或寫入鎖。
boolean hasQueuedThread(Thread thread)
// 查詢是否所有的線程正在等待獲取讀取或寫入鎖。
boolean hasQueuedThreads()
// 查詢是否有些線程正在等待與寫入鎖有關的給定條件。
boolean hasWaiters(Condition condition)
// 如果此鎖將公平性設置爲 ture,則返回 true。
boolean isFair()
// 查詢是否某個線程保持了寫入鎖。
boolean isWriteLocked()
// 查詢當前線程是否保持了寫入鎖。
boolean isWriteLockedByCurrentThread()
// 返回用於讀取操作的鎖。
ReentrantReadWriteLock.ReadLock readLock()
// 返回用於寫入操作的鎖。
ReentrantReadWriteLock.WriteLock writeLock()