ReadWriteLock
分別維護2個鎖,寫鎖是獨佔鎖,讀鎖是共享鎖,因爲讀的時間通常比寫的時間長,所以寫鎖優先級比讀鎖高
ReentrantReadWriteLock
構造
public ReentrantReadWriteLock() {
//默認獨佔
this(false);
}
public ReentrantReadWriteLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
//靜態內部類
readerLock = new ReadLock(this);
///靜態內部類
writerLock = new WriteLock(this);
}
//高16讀鎖,低16寫鎖
static final int SHARED_SHIFT = 16;
static final int SHARED_UNIT = (1 << SHARED_SHIFT);
static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
/** Returns the number of shared holds represented in count */
//返回共享個數
static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
/** Returns the number of exclusive holds represented in count */
//返回獨佔個數
static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
獲取讀寫鎖
public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }
public ReentrantReadWriteLock.ReadLock readLock() { return readerLock; }
讀鎖
lock
public void lock() {
sync.acquireShared(1);
}
protected final int tryAcquireShared(int unused) {
/*
* Walkthrough:
* 1. If write lock held by another thread, fail.
* 2. Otherwise, this thread is eligible for
* lock wrt state, so ask if it should block
* because of queue policy. If not, try
* to grant by CASing state and updating count.
* Note that step does not check for reentrant
* acquires, which is postponed to full version
* to avoid having to check hold count in
* the more typical non-reentrant case.
* 3. If step 2 fails either because thread
* apparently not eligible or CAS fails or count
* saturated, chain to version with full retry loop.
*/
///獲取當前線程
Thread current = Thread.currentThread();
//獲取當前鎖的數量
int c = getState();
//持有寫鎖失敗
if (
//獲取獨佔鎖數量!=0
exclusiveCount(c) != 0 &&
//且當前擁有獨佔訪問權限的線程不等於當前線程,這裏寫鎖可降級
getExclusiveOwnerThread() != current)
return -1;
//獲取共享鎖數量
int r = sharedCount(c);
/*
第一次線程A讀取,則記錄第一個堵得線程以及個數
第二次線程A讀取,則當前訪問線程個數+1
第三次線程B讀取,利用cachedHoldCounter緩存當前線程tid以及訪問次數
readHolds可以理解爲一級緩存,綁定了每個線程的線程計數器
cachedHoldCounter:二級緩存,緩存上一個線程執行重入鎖的次數
*/
if (//線程是否應該被阻塞
!readerShouldBlock() &&
//共享鎖數量<最大鎖數量
r < MAX_COUNT &&
//更新共享鎖數量
compareAndSetState(c, c + SHARED_UNIT)) {
//如果是第一次讀取
if (r == 0) {
//記錄第一個讀的線程
firstReader = current;
firstReaderHoldCount = 1;
} else if (firstReader == current) {
//如果當前訪問的線程是第一個訪問的線程,則訪問線程數+1
firstReaderHoldCount++;
} else {
//獲取計數器
HoldCounter rh = cachedHoldCounter;
//計數器爲null或者當前線程id不爲正在運行線程id
if (rh == null || rh.tid != getThreadId(current))
//獲取當前計數線程對應計數器
cachedHoldCounter = rh = readHolds.get();
else if (rh.count == 0)
//設置線程計數器
readHolds.set(rh);
//線程重入次數+1
rh.count++;
}
return 1;
}
//CAS尚未命中
return fullTryAcquireShared(current);
}
final int fullTryAcquireShared(Thread current) {
/*
* This code is in part redundant with that in
* tryAcquireShared but is simpler overall by not
* complicating tryAcquireShared with interactions between
* retries and lazily reading hold counts.
*/
HoldCounter rh = null;
for (;;) {
int c = getState();
//如果當前有獨佔鎖,且獨佔線程非當前線程,則返回
if (exclusiveCount(c) != 0) {
if (getExclusiveOwnerThread() != current)
return -1;
// else we hold the exclusive lock; blocking here
// would cause deadlock.
} else if (readerShouldBlock()) {
//寫鎖沒有被獲取,且讀線程被阻塞
// Make sure we're not acquiring read lock reentrantly
//當前第一個線程爲讀線程,說明當前線程重入
if (firstReader == current) {
// assert firstReaderHoldCount > 0;
} else {
if (rh == null) {
//獲取緩存的計數器
rh = cachedHoldCounter;
//沒有緩存計數器,或者計數器線程tid非當前線程tid(也就是說非上一個獲取鎖的線程)
//對寫鎖的讓步,如果第一個獲取鎖的線程是寫鎖,那麼後續所有線程AQS排隊
if (rh == null || rh.tid != getThreadId(current)) {
//獲取線程計數器
rh = readHolds.get();
//重入鎖數量爲0
if (rh.count == 0)
//刪除計數器
readHolds.remove();
}
}
//重入鎖數量爲0
if (rh.count == 0)
//AQS排隊
return -1;
}
}
//讀鎖數量超過上限,異常
if (sharedCount(c) == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
//設置讀鎖數量
//當前線程是第一個獲取讀鎖的線程,或是上一個執行任務的線程會執行到這裏
//也就是說重入獲取讀鎖的線程纔會執行到這裏
if (compareAndSetState(c, c + SHARED_UNIT)) {
//
if (sharedCount(c) == 0) {
firstReader = current;
firstReaderHoldCount = 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;
}
}
}
final boolean readerShouldBlock() {
//下一個鎖是否是獨佔鎖
return apparentlyFirstQueuedIsExclusive();
}
final boolean apparentlyFirstQueuedIsExclusive() {
Node h, s;
return (h = head) != null &&
(s = h.next) != null &&
!s.isShared() &&
s.thread != null;
}
unlock
protected final boolean tryReleaseShared(int unused) {
//獲取當前線程
Thread current = Thread.currentThread();
//當前線程爲第一個獲取讀鎖的線程
if (firstReader == current) {
// assert firstReaderHoldCount > 0;
//如果是最後一次釋放鎖,則直接置空firstReader
if (firstReaderHoldCount == 1)
firstReader = null;
else
//頭鎖重入次數-1
firstReaderHoldCount--;
} else {
//獲取上一個獲取讀鎖的線程計數器
HoldCounter rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current))
//非上一次執行的線程,則獲取當前線程計數器
rh = readHolds.get();
int count = rh.count;
if (count <= 1) {
//刪除當前線程計數器
readHolds.remove();
//說明沒有之前獲取鎖,直接釋放則異常
if (count <= 0)
throw unmatchedUnlockException();
}
//線程重入次數-1
--rh.count;
}
for (;;) {
int c = getState();
int nextc = c - SHARED_UNIT;
if (compareAndSetState(c, nextc))
// Releasing the read lock has no effect on readers,
// but it may allow waiting writers to proceed if
// both read and write locks are now free.
//鎖爲0說明正確釋放
return nextc == 0;
}
}
寫鎖
lock
protected final boolean tryAcquire(int acquires) {
//獲取當前線程
Thread current = Thread.currentThread();
///獲取當前線程狀態
int c = getState();
//獲取獨佔鎖重入數量
int w = exclusiveCount(c);
//如果有線程獲取讀寫鎖
if (c != 0) {
// (Note: if c != 0 and w == 0 then shared count != 0)
//寫鎖沒被佔用,或當前擁有獨佔訪問權限的線程不等於當前線程,說明有讀鎖被佔用,返回false
if (w == 0 || current != getExclusiveOwnerThread())
return false;
//讀寫鎖數量超過最大數量,異常
if (w + exclusiveCount(acquires) > MAX_COUNT)
throw new Error("Maximum lock count exceeded");
// Reentrant acquire
//執行到這裏,說明寫鎖被重入
setState(c + acquires);
return true;
}
//執行到這裏說明沒有讀寫鎖佔用
if (
//寫鎖是否阻塞
writerShouldBlock() ||
//修改狀態
!compareAndSetState(c, c + acquires))
//如果寫鎖沒有被阻塞,且修改狀態失敗,則返回false
return false;
//設置鎖被當前線程獨佔
setExclusiveOwnerThread(current);
return true;
}
非公平獲取鎖是否阻塞
final boolean writerShouldBlock() {
return false; // writers can always barge
}
公平獲取鎖是否阻塞
final boolean writerShouldBlock() {
return hasQueuedPredecessors();
}
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());
}
unlock
protected final boolean tryRelease(int releases) {
//擁有獨佔鎖的不是當前線程,則異常
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
int nextc = getState() - releases;
boolean free = exclusiveCount(nextc) == 0;
//獨佔鎖數量爲0,則清空鎖的持有者
if (free)
setExclusiveOwnerThread(null);
//設置鎖數量
setState(nextc);
return free;
}
鎖降級
* class CachedData {
* Object data;
* volatile boolean cacheValid;
* final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
*
* void processCachedData() {
* rwl.readLock().lock();
* if (!cacheValid) {
* // Must release read lock before acquiring write lock
* rwl.readLock().unlock();
* rwl.writeLock().lock();
* try {
* // Recheck state because another thread might have
* // acquired write lock and changed state before we did.
* if (!cacheValid) {
* data = ...
* cacheValid = true;
* }
* // Downgrade by acquiring read lock before releasing write lock
* rwl.readLock().lock();
* } finally {
* rwl.writeLock().unlock(); // Unlock write, still hold read
* }
* }
*
* try {
* use(data);
* } finally {
* rwl.readLock().unlock();
* }
* }
* }}
總結
當獲取寫鎖的情況下,當前線程依舊能獲取讀鎖,這稱之爲鎖降級
當獲取讀鎖情況下,不能獲取寫鎖
這裏始終保證了寫鎖>讀鎖等級.
避免了鎖等級一樣,出現獲取鎖的亂序問題.
讀鎖添加的State是SHARED_UNIT的倍數
這裏分別用firstReader記錄第一個獲取讀鎖的線程
cachedHoldCounter獲取上一個獲取讀鎖的線程計數器
readHolds記錄每個線程鎖對應的計數器
如果下一個鎖是獨佔鎖,且非公平模式下,則後續所有線程都進入AQS等待鎖,只有已經獲取讀鎖的依舊可以執行
final boolean readerShouldBlock() {
//下一個鎖是否是獨佔鎖
return apparentlyFirstQueuedIsExclusive();
}
protected final int tryAcquireShared(int unused) {
/////////////
if (//線程是否應該被阻塞
!readerShouldBlock() &&{
//...
}
//CAS尚未命中
return fullTryAcquireShared(current);
}
final int fullTryAcquireShared(Thread current) {
HoldCounter rh = null;
for (;;) {
int c = getState();
//如果當前有獨佔鎖,且獨佔線程非當前線程,則返回
if (exclusiveCount(c) != 0) {
if (getExclusiveOwnerThread() != current)
return -1;
/////////////////////////
} else if (readerShouldBlock()) {
/////////////////////////////////
}
//讀鎖數量超過上限,異常
if (sharedCount(c) == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
//設置讀鎖數量
//當前線程是第一個獲取讀鎖的線程,或是上一個執行任務的線程會執行到這裏
//也就是說重入獲取讀鎖的線程纔會執行到這裏
if (compareAndSetState(c, c + SHARED_UNIT)) {
//
if (sharedCount(c) == 0) {
firstReader = current;
firstReaderHoldCount = 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;
}
}
}
公平模式下直接讓下一個線程獲取鎖
final boolean readerShouldBlock() {
return hasQueuedPredecessors();
}
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());
}