关于java:Redisson-分布式锁源码-10读写锁

6次阅读

共计 2050 个字符,预计需要花费 6 分钟才能阅读完成。

前言

Redisson 还反对可重入读写锁,容许在分布式场景下,同时有多个读锁和一个写锁处于加锁状态。

应用读写锁

Redisson 读写锁实现了 JUC 下的 ReadWriteLock,应用形式基本相同。

源码

加锁源码根本和之前的可重入锁加锁无区别,惟一的差别就是在 Lua 脚本这里。

所以上面着重剖析 Lua 脚本。

读锁源码

源码地址:org.redisson.RedissonReadLock#tryLockInnerAsync

参数列表:

  1. KEYS[1]:锁名字 anyRWLock
  2. KEYS[2]:锁超时 key {锁名字}:UUID:ThreadId:rwlock_timeout 组成的字符串,{anyRWLock}:e70b1307-9ddd-43de-ac9d-9c42b5c99a0d:1:rwlock_timeout
  3. ARGV[1]:锁工夫,默认 30s
  4. ARGV[2]:以后线程,UUID:ThreadId 组成的字符串,e70b1307-9ddd-43de-ac9d-9c42b5c99a0d:1
  5. ARGV[3]:写锁名字,getWriteLockName(threadId) 写锁名字,UUID:ThreadId:write 组成的字符串,e70b1307-9ddd-43de-ac9d-9c42b5c99a0d:1:write

首次加读锁

  1. 锁不存在,间接走第一局部
  2. 设置锁 anyRWLock 的 mode 是 read,示意这是个读锁
  3. 设置锁 anyRWLock 的 e70b1307-9ddd-43de-ac9d-9c42b5c99a0d:1(以后线程)值为 1
  4. 设置锁 {anyRWLock}:e70b1307-9ddd-43de-ac9d-9c42b5c99a0d:1:rwlock_timeout:1 的值是 1,示意以后线程,以后重入的超时工夫
  5. 设置两个 RedisKey 的过期工夫
读锁重入

如果是重入的状况下:

  1. 锁存在,且是读锁,间接进入第二局部
  2. 对锁 anyRWLock 的 e70b1307-9ddd-43de-ac9d-9c42b5c99a0d:1(以后线程)值自增 1 表是重入
  3. 再创立 {anyRWLock}:e70b1307-9ddd-43de-ac9d-9c42b5c99a0d:1:rwlock_timeout:2 示意第二次加锁的超时工夫
读读反对

  1. 锁存在,进入第二局部
  2. 对以后线程的值自增 1,这里曾经是第二个线程了
  3. 设置第二个线程 {anyRWLock}:7c390320-78e3-497f-a3d8-ac34a44d0464:48:rwlock_timeout:1 的超时工夫
写读互斥

曾经加了读锁了,此时写锁进来,不满足第一局部,也不满足第二局部,所以间接返回以后锁的剩余时间。

而后再 Java 代码中进行 while (true) 自旋期待。

通过下面能够看出,在读锁的时候:

  1. 锁 anyRWLock 是哈希表构造的
  2. 加锁时,会对哈希表设置 mode 字段来示意这个锁是读锁还是写锁,mode = read 示意读锁
  3. 加锁时,会对哈希表设置以后线程 anyRWLock 的 UUID:ThreadId 字段,值示意重入次数
  4. 每次加锁,会额定保护一个 key 示意这次锁的超时工夫,这个 key 的构造是 {锁名字}:UUID:ThreadId:rwlock_timeout: 重入次数

写锁源码

源码地址:org.redisson.RedissonWriteLock#tryLockInnerAsync

参数列表:

  1. KEYS[1]:以后锁 anyRWLock
  2. ARGV[1]:锁工夫,默认 30s
  3. ARGV[2]:写锁名字,UUID:ThreadId:write 组成的字符串,c69a9ed4-5c30-4952-814e-c0b94ad03a7f:1:write

写锁源码绝对比拟好了解:

  1. 判断锁的模式,是写锁
  2. 锁不存在间接创立
  3. 锁存在,再判断是不是本人,是本人则重入

这么下来,能够看出间接满足,写写互斥,读写互斥,以后线程又能够重入。

总结

到这里基本上读写锁就看完了,读锁实现的略微简单一些,写锁简单明了。

在读锁的时候:

  1. 锁 anyRWLock 是哈希表构造
  2. 加锁时,会对哈希表设置 mode 字段来示意这个锁是读锁还是写锁,mode = read 示意读锁
  3. 加锁时,会对哈希表设置以后线程 anyRWLock 的 UUID:ThreadId 字段,值示意重入次数
  4. 每次加锁,会额定保护一个 key 示意这次锁的超时工夫,这个 key 的构造是 {锁名字}:UUID:ThreadId:rwlock_timeout: 重入次数

在写锁的时候:

  1. 锁 anyRWLock 是哈希表构造
  2. 加锁时,会对哈希表设置 mode 字段来示意这个锁是读锁还是写锁,mode = write 示意写锁
  3. 在 anyRWLock 中再额定保护一个字段 UUID:ThreadId:write 示意重入次数

至于看门狗,这些都和之前的一样,就不额定介绍了。

相干举荐

  • Redisson 分布式锁源码 09:RedLock 红锁的故事
  • Redisson 分布式锁源码 08:MultiLock 加锁与锁开释
  • Redisson 分布式锁源码 07:偏心锁开释
正文完
 0