目錄
一、基本原理
二、源碼解析:
(2)獲取鎖
(1)釋放鎖:
? ? ? ?
????????之前給大家介紹過redisson的分布式鎖,用redisson來實現比自己手搓簡單的分布式鎖有很多好處,因為這些可重入、可重試的邏輯較為復雜,他們的lua腳本不可能讓我們在開發時自己實現,這樣太耗時間了。所以redisson就幫我們實現了可重入和可重試。但我們也要知道他的原理,這期我們先講可重入。
上一篇:
【Redisson】快速實現分布式鎖-CSDN博客
一、基本原理
基本原理:
(1)獲取鎖的時候,還是使用setnx命令,如果該鎖還沒有被獲取過,直接set,也就是獲取鎖成功
(2)當該線程第二次獲取鎖時,因為鎖已經被獲取了,也就是setnx返回false。這時候,先不直接返回獲取鎖失敗的邏輯,而是先判斷該鎖的value值是不是自己,如果是,那么就獲取鎖成功。
(3)有一個計數器,每次獲取鎖成功計數器就+1,每次釋放鎖的時候計數器就-1。當計數器為0的時候表明該線程所有重入的鎖都被釋放完畢了,就可以刪除這個key。那么其他線程就可以獲取鎖了
(4)因為key的value值既要記錄線程標識,也要記錄重入次數。所以String類型的結構就不滿足了。需要使用到hash結構
(5)注意:每次釋放鎖時,如果value值不是0,說明該鎖還是被該線程占用的。也就是釋放重入鎖的時候,要重置鎖的有效期
圖解:
二、源碼解析:
(2)獲取鎖
<T> RFuture<T> tryLockInnerAsync(long waitTime, long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand<T> command) {return this.commandExecutor.syncedEvalNoRetry(this.getRawName(), LongCodec.INSTANCE, command, "local mode = redis.call('hget', KEYS[1], 'mode');" +" if (mode == false) then " +" redis.call('hset', KEYS[1], 'mode', 'read');" +" redis.call('hset', KEYS[1], ARGV[2], 1);" +" redis.call('set', KEYS[2] .. ':1', 1);" +" redis.call('pexpire', KEYS[2] .. ':1', ARGV[1]);" +" redis.call('pexpire', KEYS[1], ARGV[1]);" +" return nil;" +" end;" +" if (mode == 'read') or (mode == 'write' and redis.call('hexists', KEYS[1], ARGV[3]) == 1) then" +" local ind = redis.call('hincrby', KEYS[1], ARGV[2], 1);" +" local key = KEYS[2] .. ':' .. ind;redis.call('set', key, 1);" +" redis.call('pexpire', key, ARGV[1]);" +" local remainTime = redis.call('pttl', KEYS[1]);" +" redis.call('pexpire', KEYS[1], math.max(remainTime, ARGV[1]));" +" return nil;" +" end;" + "return redis.call('pttl', KEYS[1]);",Arrays.asList(this.getRawName(), this.getReadWriteTimeoutNamePrefix(threadId)), new Object[]{unit.toMillis(leaseTime), this.getLockName(threadId), this.getWriteLockName(threadId)});}
解析:
(1)釋放鎖:
解析:?