Redisson(2-3)分布式锁实现对比 VS Java的ReentrantLock的FairLock
?Redisson實現了一整套JDK中ReentrantLock的功能,這里對比一下公平鎖(Fair)實現的差異和核心的思想。
?
公平鎖存在的意義是為了保證絕對的公平,但是有其弊端,這個在網上有很多相關的解釋,就是說絕對的公平不一定是性能最高的,因此和它相對的還有非公平鎖,但是費公平鎖也有問題,會引發饑餓現象。具體解釋也可參見AbstractQueuedSynchronizer(九)——ReentrantLock公平和非公平鎖_普通網友的博客-CSDN博客
fair模式的帶超時時間的tryLock(超時時間)
ReentrantLock
ReentrantLock實現公平鎖依賴的是一個叫做hasQueuedPredecessors的方法,所有的加鎖操作前都要先判斷這個方法的返回值,
方法的注釋寫的很清楚:
檢驗是否有其他線程已經等待了更長時間,借此保證公平。此外,注釋還寫道:
這兩個&&判斷也可以實現同樣的功能,同時語義更清晰,但是效率相比之下沒有前者的數據結構操作高。
總結下來,單虛擬機內部的公平操作依仗的是鏈表數據結構的幫助,將所有申請鎖的線程按照訪問的優先級排序,從而保證了這些申請鎖的線程得到鎖的公平性。那么對于跨虛擬機的場景要如何處理呢?類比一下,本地鎖對應分布式鎖,那么鏈表(隊列)對應的就是分布式隊列了,正好Redis也有對應的數據結構來支撐這個功能。
Redisson
Redisson利用了redis本身的集合操作配合lua腳本來解決這個問題,這個過程和非公平鎖比起來要復雜的多。
這里會根據command分成兩組,一組是EVAL_NULL_BOOLEAN,tryAcquireOnce的語義,返回的是Boolean,另一組是EVAL_LONG,返回的是Long,即當前鎖的ttl,用來實現lockInterruptibly當獲取鎖失敗時用于等待下次競爭鎖的時間。
EVAL_NULL_BOOLEAN:
首先看第一段死循環,如注釋所寫,這段邏輯是清理已經過期的線程:
具體邏輯,首先判斷存儲線程的隊列/列表中是否有線程存在,當列表中的頭元素是空的話,說明沒有過期線程,這樣就可以break進行下面的鎖操作邏輯。
如果隊列不為空,就挨個檢測存儲的線程是否已經過期(過期的時間點是否已經是過去的某個時刻,即比當前時刻小),如果過期,那么將該線程從隊列中移除,同時將保存該線程過期時間點的數據也從對應的隊列中移除。
清理過程結束后,進行真正的鎖操作邏輯:
①如果當前鎖不存在,同時,存線程id的有序隊列不存在或者隊列存在且當前線程處于隊列頭(表明當前線程可以獲取到鎖)
②那么pop將當前threadId從隊列中移除,保證下次下一個線程可以搶鎖,zrem移除鎖超時隊列的threadId。
③threadId獲取到鎖,加鎖,并設置重入次數為1
④對該鎖設置超時時間
⑤返回nil(因為上面的指令是EVAL_NULL_BOOLEAN,所以這里返回的是true)
上面的①如果是false:
②看看當前線程是否已經獲取到鎖
③如果獲取到,那么用hincrby將重入次數計數加一
④重新設置過期時間
⑤返回nil(因為上面的指令是EVAL_NULL_BOOLEAN,所以這里返回的是true)
EVAL_LONG:
對于EVAL_LONG,唯一不同的地方在于,當獲取不到鎖的時候,因為有睡眠等待的語義,所以需要返回ttl,而不是直接tryAcquireOnce返回Boolean,所以lua腳本有所不同,具體在下圖描述的這一部分:
如果存儲線程的優先隊列中的第一個線程不是當前請求鎖的線程,那么ttl就是這優先隊列中第一個線程的ttl。否則,當前線程和優先隊列中第一個線程是同一個線程(可以獲取到鎖),那么ttl就是該鎖的ttl。
然后將該線程和該線程的ttl分別加入到對應的優先隊列中,zadd執行返回1,表示新增成功(如果是已存在的元素,表示更新操作,返回值不是1),說明該thread之前不在隊列中,此時通過rpush將其添加到存儲線程的優先隊列中去。
疑問:
這里有個問題還沒看明白,就是這里有個threadWaitTime,設置時間是5000ms,不知道是什么作用?
看完了lua腳本再補充說幾個要點:
①關于發布訂閱
我們看到FairLock重載了這兩個方法,和普通的鎖相比,加入了threadId屬性。這是為什么呢?因為這是公平鎖,redis中利用優先隊列保存了當前等待獲取鎖的所有線程,所以需要按照這些線程的優先順序來獲取鎖,所以要獲得下一個能獲得鎖的線程,只發布一個能讓該線程訂閱到的消息來執行操作。
總結
以上是生活随笔為你收集整理的Redisson(2-3)分布式锁实现对比 VS Java的ReentrantLock的FairLock的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: windows商店_Windows 10
- 下一篇: java美元兑换,(Java实现) 美元