ReentrantReadWriteLock原始碼解析
ReentrantReadWriteLock
使用一個 32
位的 int
型別來表示鎖被佔用的執行緒數,高 16
位用來表示讀鎖佔有的執行緒數量,低 16
位表示寫鎖被同一個執行緒申請次數。
// 讀鎖佔用位數高16位
static final int SHARED_SHIFT = 16;
// 增加讀鎖數量
static final int SHARED_UNIT = (1 << SHARED_SHIFT);
// 申請讀鎖最大執行緒數量(65535)
static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
// 寫鎖重入次數
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
// 當前執行緒持有讀鎖的重入次數,只在構造和readObject中初始化重入次數為0時刪除
private transient ThreadLocalHoldCounter readHolds;
// 最後一個獲取讀鎖執行緒的重入計數
private transient HoldCounter cachedHoldCounter;
// 第一個獲得讀鎖的執行緒
private transient Thread firstReader = null;
// 第一個獲得讀鎖的執行緒重入計數
private transient int firstReaderHoldCount;
ReentrantReadWriteLock
有公平鎖與非公平鎖實現,這裡主要看非公平鎖實現。
public ReentrantReadWriteLock() {
this(false);
}
public ReentrantReadWriteLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
readerLock = new ReadLock(this);
writerLock = new WriteLock(this);
}
讀鎖加鎖
// ReentrantReadWriteLock.ReadLock
public void lock() {
sync.acquireShared(1);
}
// AbstractQueuedSynchronizer
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0)
doAcquireShared(arg);
}
// ReentrantReadWriteLock
protected final int tryAcquireShared(int unused) {
Thread current = Thread.currentThread();
int c = getState();
// 獨佔鎖的重入次數不等於0 且 獨佔鎖持有執行緒不等於當前執行緒,則返回-1獲取共享鎖失敗
if (exclusiveCount(c) != 0 &&
getExclusiveOwnerThread() != current)
return -1;
int r = sharedCount(c); // 持有共享鎖的執行緒數量
// 判斷獲取讀鎖的執行緒是否需要阻塞 且 持有共享鎖執行緒數量小於最大執行緒數量 且 CAS設定持有共享鎖執行緒數量成功
if (!readerShouldBlock() &&
r < MAX_COUNT &&
compareAndSetState(c, c + SHARED_UNIT)) {
// 還沒有執行緒持有共享鎖
if (r == 0) {
firstReader = current; // 設定當前執行緒為第一個獲取共享鎖的執行緒
firstReaderHoldCount = 1; // 第一個獲取讀鎖的執行緒重入次數設定為1
} else if (firstReader == current) {
// 第一個獲取共享鎖的執行緒與當前執行緒相同,則增加重入次數
firstReaderHoldCount++;
} else {
HoldCounter rh = cachedHoldCounter;
// 最後一個獲取讀鎖執行緒的重入計數為空 或 其執行緒id與當前執行緒id不一致,則將當前執行緒的重入次數設定為cachedHoldCounter
if (rh == null || rh.tid != getThreadId(current))
cachedHoldCounter = rh = readHolds.get();
else if (rh.count == 0)
readHolds.set(rh);
rh.count++; // 自增當前執行緒重入次數
}
return 1;
}
return fullTryAcquireShared(current); // CAS失敗或其它原因則呼叫此方法處理
}
// ReentrantReadWriteLock
final int fullTryAcquireShared(Thread current) {
HoldCounter rh = null;
for (;;) {
int c = getState();
// 獨佔鎖的重入次數不等於0 且 獨佔鎖持有執行緒不等於當前執行緒,則返回-1獲取共享鎖失敗
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;
// 最後一個獲取讀鎖執行緒的重入計數為空 或 其執行緒id與當前執行緒id不一致
if (rh == null || rh.tid != getThreadId(current)) {
rh = readHolds.get();
// 當前執行緒持有讀鎖的重入次數等於0,則移除改計數物件
if (rh.count == 0)
readHolds.remove();
}
}
// 重入次數為0,返回-1表示獲取共享鎖失敗
if (rh.count == 0)
return -1;
}
}
// 超過讀鎖最大執行緒數量丟擲異常
if (sharedCount(c) == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
// CAS設定持有共享鎖執行緒數量
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;
}
}
}
讀鎖釋放
// ReentrantReadWriteLock
public void unlock() {
sync.releaseShared(1);
}
// AbstractQueuedSynchronizer
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
// ReentrantReadWriteLock
protected final boolean tryReleaseShared(int unused) {
Thread current = Thread.currentThread();
// 判斷第一個獲取讀鎖的執行緒與當前執行緒是否相同
if (firstReader == current) {
// assert firstReaderHoldCount > 0;
// 如果重入次數為1,則直接置空firstReader
if (firstReaderHoldCount == 1)
firstReader = null;
else
firstReaderHoldCount--; // 重入次數自減
} else {
HoldCounter rh = cachedHoldCounter;
// 最後一個獲取讀鎖執行緒的重入計數為空 或 其執行緒id與當前執行緒id不一致
if (rh == null || rh.tid != getThreadId(current))
rh = readHolds.get();
int count = rh.count;
// 如果當前執行緒的鎖重入次數<=1,則直接移除該計數物件
if (count <= 1) {
readHolds.remove();
if (count <= 0)
throw unmatchedUnlockException();
}
--rh.count; // 自減鎖重入次數
}
for (;;) {
int c = getState();
int nextc = c - SHARED_UNIT;
// CAS設定同步state
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
寫鎖加鎖
// ReentrantReadWriteLock.WriteLock
public void lock() {
sync.acquire(1);
}
// AbstractQueuedSynchronizer
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
// ReentrantReadWriteLock.Sync
protected final boolean tryAcquire(int acquires) {
Thread current = Thread.currentThread();
int c = getState(); // 獲取當前同步狀態
int w = exclusiveCount(c); // 獲取獨佔鎖的重入次數
// c不等於0說明當前讀鎖或寫鎖被佔用
if (c != 0) {
// (Note: if c != 0 and w == 0 then shared count != 0)
// 獨佔鎖重入次數等於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;
}
// 判斷寫鎖是否需要阻塞 或者 CAS設定state失敗,返回false獲取寫鎖失敗
if (writerShouldBlock() ||
!compareAndSetState(c, c + acquires))
return false;
setExclusiveOwnerThread(current); // 設定獨佔鎖持有物件為當前執行緒
return true; // 獲取鎖成功
}
寫鎖釋放
// ReentrantReadWriteLock.WriteLock
public void unlock() {
sync.release(1);
}
// AbstractQueuedSynchronizer
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
// ReentrantReadWriteLock.Sync
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;
}
相關文章
- 深入淺出ReentrantReadWriteLock原始碼解析原始碼
- Java併發之ReentrantReadWriteLock原始碼解析(一)Java原始碼
- Java併發之ReentrantReadWriteLock原始碼解析(二)Java原始碼
- ReentrantReadWriteLock原始碼分析原始碼
- ReentrantReadWriteLock原始碼分析及理解原始碼
- Java併發包原始碼學習系列:ReentrantReadWriteLock讀寫鎖解析Java原始碼
- java原始碼-ReentrantReadWriteLock寫鎖介紹Java原始碼
- Java 讀寫鎖 ReentrantReadWriteLock 原始碼分析Java原始碼
- 原始碼分析:ReentrantReadWriteLock之讀寫鎖原始碼
- Java JUC ReentrantReadWriteLock解析Java
- JUC原始碼學習筆記6——ReentrantReadWriteLock原始碼筆記
- 【JUC】JDK1.8原始碼分析之ReentrantReadWriteLock(七)JDK原始碼
- 【原始碼解析】- ArrayList原始碼解析,絕對詳細原始碼
- Spark原始碼-SparkContext原始碼解析Spark原始碼Context
- CountDownLatch原始碼解析CountDownLatch原始碼
- LeakCanary原始碼解析原始碼
- vuex原始碼解析Vue原始碼
- ArrayBlockQueue原始碼解析BloC原始碼
- AsyncTask原始碼解析原始碼
- CopyOnWriteArrayList原始碼解析原始碼
- Express原始碼解析Express原始碼
- Observer原始碼解析Server原始碼
- SparseArray 原始碼解析原始碼
- RecyclerView原始碼解析View原始碼
- Promise 原始碼解析Promise原始碼
- Koa原始碼解析原始碼
- RateLimiter原始碼解析MIT原始碼
- redux原始碼解析Redux原始碼
- SDWebImage原始碼解析Web原始碼
- CyclicBarrier原始碼解析原始碼
- Semaphore原始碼解析原始碼
- Exchanger原始碼解析原始碼
- AbstractQueuedSynchronizer原始碼解析原始碼
- OKio原始碼解析原始碼
- Koa 原始碼解析原始碼
- RxPermission原始碼解析原始碼
- MyBatis原始碼解析MyBatis原始碼
- ArrayList原始碼解析原始碼