java原始碼-ReentrantReadWriteLock寫鎖介紹
開篇
這篇文章主要從原始碼角度講解ReentrantReadWriteLock的WriteLock的加鎖和減鎖過程。
ReentrantReadWriteLock的WriteLock加鎖解鎖過程依賴於AbstractQueuedSynchronizer(AQS)類,所以有些相同的邏輯可以看看ReentrantLock的邏輯。
- ReentrantReadWriteLock的資料結構介紹
- java原始碼 – ReentrantReadWriteLock讀鎖介紹
- java原始碼 – ReentrantReadWriteLock寫鎖介紹
加鎖過程
- WriteLock的lock()內部通過sync.acquire(1)獲取鎖。
- 嘗試通過tryAcquire獲取寫鎖,如果獲取成功那麼就成功佔用寫鎖。
- 獲取寫鎖失敗後,將當前執行緒新增到寫鎖喚醒佇列當中acquireQueued(addWaiter(Node.EXCLUSIVE), arg))。
- acquireQueued(addWaiter(Node.EXCLUSIVE), arg))的操作邏輯和ReentrantLock的邏輯一致。
public static class WriteLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = -4992448646407690164L;
private final Sync sync;
protected WriteLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
public void lock() {
sync.acquire(1);
}
}
public final void acquire(int arg) {
// 1、先嚐試獲取鎖tryAcquire
// 2、獲鎖失敗就addWaiter操作
// 3、acquireQueued判斷是否喚醒
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
tryAcquire過程
- 獲取鎖狀態state變數,並獲取寫鎖佔用的計數值。
- 當前state不為0,如果寫鎖狀態為0說明讀鎖被佔用,返回鎖佔用失敗。
- 鎖狀態state不為空且佔鎖執行緒為當前執行緒,說明鎖被其他執行緒佔用返回鎖佔用失敗。
- 寫鎖重入數溢位,返回鎖佔用失敗。
- 如果寫鎖阻塞 或者 設定state狀態失敗,返回鎖佔用失敗。
- 設定當前鎖佔用執行緒為當前執行緒,返回鎖佔用成功。
protected final boolean tryAcquire(int acquires) {
Thread current = Thread.currentThread();
// 獲取鎖狀態state變數
int c = getState();
// 獲取寫鎖佔用的計數
int w = exclusiveCount(c);
// 如果鎖狀態state不為0
if (c != 0) {
// 1、當前state不為0,如果寫鎖狀態為0說明讀鎖此時被佔用,說明鎖被讀鎖佔用
// 2、鎖狀態state不為空且佔鎖執行緒為當前執行緒(屬於鎖重入),說明鎖被其他執行緒佔用
if (w == 0 || current != getExclusiveOwnerThread())
return false;
// 寫鎖重入數溢位
if (w + exclusiveCount(acquires) > MAX_COUNT)
throw new Error("Maximum lock count exceeded");
// 寫鎖獲取成功返回成功標記
setState(c + acquires);
return true;
}
// 如果寫鎖阻塞 或者 設定state狀態失敗,那麼就代表獲鎖失敗
if (writerShouldBlock() ||
!compareAndSetState(c, c + acquires))
return false;
// 設定當前鎖佔用執行緒為當前執行緒
setExclusiveOwnerThread(current);
return true;
}
解鎖過程
- WriteLock的unlock()內部通過sync. release(1)釋放鎖。
- 嘗試通過tryRelease()方法來釋放鎖並喚醒下一個等待執行緒。
- 在喚醒過程中需要仔細看看讀寫鎖等待執行緒喚醒的細節,待補充
public void unlock() {
sync.release(1);
}
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
tryRelease過程
- 判斷當前執行緒和鎖佔用執行緒不一致isHeldExclusively()丟擲異常。
- 鎖狀態減去當前釋放動作傳入引數nextc = getState() – releases。
- 判斷鎖狀態的寫狀態為0就表明當前執行緒已經完全釋放鎖。
- 當前執行緒完全釋放鎖,然後設定鎖佔用執行緒為null並設定鎖狀態。
protected final boolean tryRelease(int releases) {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
int nextc = getState() - releases;
boolean free = exclusiveCount(nextc) == 0;
if (free)
setExclusiveOwnerThread(null);
setState(nextc);
return free;
}
相關文章
- Java 讀寫鎖 ReentrantReadWriteLock 原始碼分析Java原始碼
- Java併發指南10:Java 讀寫鎖 ReentrantReadWriteLock 原始碼分析Java原始碼
- 原始碼分析:ReentrantReadWriteLock之讀寫鎖原始碼
- Java併發包原始碼學習系列:ReentrantReadWriteLock讀寫鎖解析Java原始碼
- Java併發——讀寫鎖ReentrantReadWriteLockJava
- 讀寫鎖ReentrantReadWriteLock
- 讀寫鎖 ReentrantReadWriteLock
- AQS之ReentrantReadWriteLock寫鎖AQS
- Java併發程式設計-讀寫鎖(ReentrantReadWriteLock)Java程式設計
- Java鎖之ReentrantReadWriteLockJava
- 讀寫鎖 ReentrantReadWriteLock 與 互斥鎖 的效率
- Java併發程式設計之鎖機制之ReentrantReadWriteLock(讀寫鎖)Java程式設計
- 輕鬆掌握java讀寫鎖(ReentrantReadWriteLock)的實現原理Java
- ReentrantReadWriteLock讀寫鎖及其在 RxCach
- 深入理解讀寫鎖ReentrantReadWriteLock
- Lock介面、重入鎖ReentrantLock、讀寫鎖ReentrantReadWriteLockReentrantLock
- Java中15種鎖的介紹Java
- Java併發之ReentrantReadWriteLock原始碼解析(一)Java原始碼
- Java併發之ReentrantReadWriteLock原始碼解析(二)Java原始碼
- ReentrantReadWriteLock原始碼解析原始碼
- ReentrantReadWriteLock原始碼分析原始碼
- Java中的讀寫鎖ReentrantReadWriteLock詳解,存在一個小缺陷Java
- ORACLE鎖介紹Oracle
- 介紹 golang net/http 原始碼GolangHTTP原始碼
- Java字串編碼介紹Java字串編碼
- ReentrantReadWriteLock讀寫鎖及其在 RxCache 中的使用
- Java 種15種鎖的介紹:公平鎖,可重入鎖,獨享鎖,互斥鎖等等Java
- Java 種15種鎖的介紹:公平鎖,可重入鎖,獨享鎖,互斥鎖等等...Java
- MySQL內部實現讀鎖和寫鎖的具體鎖定型別介紹MySql型別
- ReentrantReadWriteLock原始碼分析及理解原始碼
- Golang 讀寫鎖RWMutex 互斥鎖Mutex 原始碼詳解GolangMutex原始碼
- golang RWMutex讀寫互斥鎖原始碼分析GolangMutex原始碼
- ReentrantLock介紹及原始碼解析ReentrantLock原始碼
- Spring原始碼分析——spring原始碼之obtainFreshBeanFactory()介紹Spring原始碼AIBean
- 深入淺出ReentrantReadWriteLock原始碼解析原始碼
- Oracle鎖簡單介紹Oracle
- ORACLE 鎖簡單介紹Oracle
- Dubbo原始碼學習之-SPI介紹原始碼