深入淺出ReentrantReadWriteLock原始碼解析
阿新 • • 發佈:2020-07-17
> 讀寫鎖實現邏輯相對比較複雜,但是卻是一個經常使用到的功能,希望將我對`ReentrantReadWriteLock`的原始碼的理解記錄下來,可以對大家有幫助
## 前提條件
在理解`ReentrantReadWriteLock`時需要具備一些基本的知識
### 理解AQS的實現原理
之前有寫過一篇[《深入淺出AQS原始碼解析》](https://www.cnblogs.com/pinxiong/p/13288201.html)關於AQS的文章,對AQS原理不瞭解的同學可以先看一下
### 理解ReentrantLock的實現原理
`ReentrantLock`的實現原理可以參考[《深入淺出ReentrantLock原始碼解析》](https://www.cnblogs.com/pinxiong/p/13304210.html)
### 什麼是讀鎖和寫鎖
對於資源的訪問就兩種形式:要麼是讀操作,要麼是寫操作。讀寫鎖是將被鎖保護的臨界資源的讀操作和寫操作分開,允許同時有多個執行緒同時對臨界資源進行讀操作,任意時刻只允許一個執行緒對資源進行寫操作。簡單的說,對與讀操作採用的是**共享鎖**,對於寫操作採用的是**排他鎖**。
### 讀寫狀態的設計
`ReentrantReadWriteLock`是用`state`欄位來表示讀寫鎖重複獲取資源的次數,高16位用來標記讀鎖的同步狀態,低16位用來標記寫鎖的同步狀態
```
// 劃分的邊界線,用16位來劃分
static final int SHARED_SHIFT = 16;
// 讀鎖的基本單位,也就是讀鎖加1或者減1的基本單位(1左移16位後的值)
static final int SHARED_UNIT = (1 << SHARED_SHIFT);
// 讀寫鎖的最大值(在計算讀鎖的時候需要先右移16位)
static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
// 寫鎖的掩碼,state值與掩碼做與運算後得到寫鎖的真實值
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
// 獲取資源被讀鎖佔用的次數
static int sharedCount(int c){
return c >>> SHARED_SHIFT;
}
// 獲取資源被寫鎖佔用的次數
static int exclusiveCount(int c){
return c & EXCLUSIVE_MASK;
}
```
在統計讀鎖被每個執行緒持有的次數時,`ReentrantReadWriteLock`採用的是`HoldCounter`來實現的,具體如下:
```
// 持有讀鎖的執行緒重入的次數
static final class HoldCounter {
// 重入的次數
int count = 0;
// 持有讀鎖執行緒的執行緒id
final long tid = getThreadId(Thread.currentThread());
}
/**
* 採用ThreadLocal機制,做到執行緒之間的隔離
*/
static final class ThreadLocalHoldCounter
extends Thr