Redission支持可重入读写锁RReadWriteLock,允许同时有多个读锁或者一个写锁处于加锁状态。RReadWriteLock实现了juc.lock.ReadWriteLock接口,其中读锁和写锁都继承了RLock接口。
RReadWriteLock使用方法如下:
1 | RReadWriteLock rwlock = redisson.getReadWriteLock("anyRWLock"); |
为了解决死锁问题,在读写锁中依然使用看门狗机制不断延长有效期,默认超时时间为30秒。
读锁
加读锁
在Redission读写锁中,读锁在以下情况可以加锁成功:
- 无锁或者其他线程只加过读锁
- 同一个线程重复加读锁
- 同一线程先加写锁后加读锁
与可重入锁相比,读写锁锁结构有所不同,hash中存在一个标记锁模式的field以及多个标记加锁线程的field,所以在读锁加锁时,lua脚本存在差异:
1 | <T> RFuture<T> tryLockInnerAsync(long waitTime, long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand<T> command) { |
watchdog维持读锁
由于读写锁结构不同于一般可重入锁,所以watchdog维持锁的lua脚本也有所不同:
1 | protected RFuture<Boolean> renewExpirationAsync(long threadId) { |
解锁读锁
在读锁进行解锁时,需要删除或者减少当前线程读锁重入次数,并且更新过期时间:
1 | protected RFuture<Boolean> unlockInnerAsync(long threadId) { |
写锁
Redission的读写锁中,写锁只有在以下情况才能加锁成功:
- 没有任何线程加过锁
- 同一个线程重复加写锁
加写锁
加写锁时相对简单,只需要判断是否加过锁、是否是当前线程加过写锁:
1 | <T> RFuture<T> tryLockInnerAsync(long waitTime, long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand<T> command) { |
watchdog维持写锁
写锁结构与普通可重入锁结构一致,watchdog机制同RedissonLock,不再复述。
写锁解锁
当只有写锁解锁时,要么直接删除锁,要么减少写锁重入次数并且更新过期时间。当既有写锁又有读锁时,锁模式为写锁模式,在需要删除写锁时,还需要把锁模式转变为读模式。
1 | protected RFuture<Boolean> unlockInnerAsync(long threadId) { |