Redisson 分布式鎖源碼 10:讀寫鎖

前言
Redisson 還支持可重入讀寫鎖,允許在分布式場景下,同時有多個讀鎖和一個寫鎖處于加鎖狀態(tài)。
1
使用讀寫鎖
Redisson 讀寫鎖實現(xiàn)了 JUC 下的 ReadWriteLock,使用方式基本相同。

2
源碼
加鎖源碼基本和之前的可重入鎖加鎖無區(qū)別,唯一的差異就是在 Lua 腳本這里。
所以下面著重分析 Lua 腳本。
讀鎖源碼
源碼地址:org.redisson.RedissonReadLock#tryLockInnerAsync
參數(shù)列表:
KEYS[1]:鎖名字 anyRWLock KEYS[2]:鎖超時 key {鎖名字}:UUID:ThreadId:rwlock_timeout組成的字符串,{anyRWLock}:e70b1307-9ddd-43de-ac9d-9c42b5c99a0d:1:rwlock_timeoutARGV[1]:鎖時間,默認 30s ARGV[2]:當前線程, UUID:ThreadId組成的字符串,e70b1307-9ddd-43de-ac9d-9c42b5c99a0d:1ARGV[3]:寫鎖名字, getWriteLockName(threadId)寫鎖名字,UUID:ThreadId:write組成的字符串, e70b1307-9ddd-43de-ac9d-9c42b5c99a0d:1:write

首次加讀鎖

鎖不存在,直接走第一部分 設置鎖 anyRWLock 的 mode 是 read,表示這是個讀鎖 設置鎖 anyRWLock 的 e70b1307-9ddd-43de-ac9d-9c42b5c99a0d:1(當前線程)值為 1 設置鎖 {anyRWLock}:e70b1307-9ddd-43de-ac9d-9c42b5c99a0d:1:rwlock_timeout:1 的值是 1,表示當前線程,當前重入的超時時間 設置兩個 RedisKey 的過期時間
讀鎖重入

如果是重入的情況下:
鎖存在,且是讀鎖,直接進入第二部分 對鎖 anyRWLock 的 e70b1307-9ddd-43de-ac9d-9c42b5c99a0d:1(當前線程)值自增 1 表是重入 再創(chuàng)建 {anyRWLock}:e70b1307-9ddd-43de-ac9d-9c42b5c99a0d:1:rwlock_timeout:2 表示第二次加鎖的超時時間
讀讀支持

鎖存在,進入第二部分 對當前線程的值自增 1,這里已經(jīng)是第二個線程了 設置第二個線程 {anyRWLock}:7c390320-78e3-497f-a3d8-ac34a44d0464:48:rwlock_timeout:1 的超時時間
寫讀互斥
已經(jīng)加了讀鎖了,此時寫鎖進來,不滿足第一部分,也不滿足第二部分,所以直接返回當前鎖的剩余時間。
然后再 Java 代碼中進行 while (true) 自旋等待。
通過上面可以看出,在讀鎖的時候:
鎖 anyRWLock 是哈希表結(jié)構(gòu)的 加鎖時,會對哈希表設置 mode 字段來表示這個鎖是讀鎖還是寫鎖, mode = read表示讀鎖加鎖時,會對哈希表設置當前線程 anyRWLock 的 UUID:ThreadId字段,值表示重入次數(shù)每次加鎖,會額外維護一個 key 表示這次鎖的超時時間,這個 key 的結(jié)構(gòu)是 {鎖名字}:UUID:ThreadId:rwlock_timeout:重入次數(shù)
寫鎖源碼
源碼地址:org.redisson.RedissonWriteLock#tryLockInnerAsync
參數(shù)列表:
KEYS[1]:當前鎖 anyRWLock ARGV[1]:鎖時間,默認 30s ARGV[2]:寫鎖名字, UUID:ThreadId:write組成的字符串,c69a9ed4-5c30-4952-814e-c0b94ad03a7f:1:write

寫鎖源碼相對比較好理解:
判斷鎖的模式,是寫鎖 鎖不存在直接創(chuàng)建 鎖存在,再判斷是不是自己,是自己則重入

這么下來,可以看出直接滿足,寫寫互斥,讀寫互斥,當前線程又可以重入。
3
總結(jié)
到這里基本上讀寫鎖就看完了,讀鎖實現(xiàn)的稍微復雜一些,寫鎖簡單明了。
在讀鎖的時候:
鎖 anyRWLock 是哈希表結(jié)構(gòu) 加鎖時,會對哈希表設置 mode 字段來表示這個鎖是讀鎖還是寫鎖, mode = read表示讀鎖加鎖時,會對哈希表設置當前線程 anyRWLock 的 UUID:ThreadId字段,值表示重入次數(shù)每次加鎖,會額外維護一個 key 表示這次鎖的超時時間,這個 key 的結(jié)構(gòu)是 {鎖名字}:UUID:ThreadId:rwlock_timeout:重入次數(shù)
在寫鎖的時候:
鎖 anyRWLock 是哈希表結(jié)構(gòu) 加鎖時,會對哈希表設置 mode 字段來表示這個鎖是讀鎖還是寫鎖, mode = write表示寫鎖在 anyRWLock 中再額外維護一個字段 UUID:ThreadId:write表示重入次數(shù)
至于看門狗,這些都和之前的一樣,就不額外介紹了。
- <End /> -
歷史文章 | 相關(guān)推薦

評論
圖片
表情
