复制代码
tryLock 方法参数说明:
尝试加锁方法 tryLock , 两个重要的入参 waitTime、leaseTime:
- waitTime: 尝试加锁的最大时间 , 如果在这个时间内一直没有加锁成功 , 则返回 false 。
- leaseTime: 锁的有效期 , 如果客户端(进程)在这个时间内没有释放锁 , 则 Redis 主动释放 , 当然 Redisson 看门狗的机制会将这个时间延期 , 后面会说到 。
- 尝试加锁 tryAcquire , 如果加锁成功则返回 null , 如果锁被占用 , 则返回锁的剩余时间 ttl 。
- 如果加锁成功返回 true , 否在判断 waitTime 是否过期 , 过期则加锁失败返回 false 。
- 基于信号量 , 通过 Redis 的发布订阅 , 订阅锁的释放事件 , 一旦锁释放会立即通知等待的线程去竞争锁 。
- 线程阻塞剩余 waitTime 时间 , 来等待锁释放的通知 , 如果阻塞时间超过了剩余 waitTime 时间 , 则取消任务 , 取消任务成功再取消订阅信息 , 加锁失败返回 false;否则在剩余 waitTime 时间内等到了锁释放通知 , 则进入循环加锁阶段 。
- 循环中继续以同样的方式加锁 , 如果在剩余 waitTime 内加锁成功返回 true , 否在加锁失败返回 false 。
- 如果在剩余 waitTime 时间内 , 锁还是被其他的客户端(进程)持有 , 阻塞指定时间(持有锁的剩余过期时间和剩余 waitTime 时间)等待锁的释放消息 。
- 具体实现:利用信号量(semaphore)阻塞当前线程获取许可 , 如果有可用许可则继续尝试加锁 , 如果没有可用许可则阻塞给定的时间 , 直至其他线程释放锁 , 调用 release() 方法增加许可 , 或者其它某些线程中断当前线程 , 或者已超出指定的等待时间 。
- 如果剩余 waitTime 过期 , 加锁失败返回 false 。
<T> RFuture<T> tryLockInnerAsync(long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand<T> command) {internalLockLeaseTime = unit.toMillis(leaseTime);return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, command,"if (redis.call('exists', KEYS[1]) == 0) then " +// 1、如果 Redis 中不存在这个 key"redis.call('hset', KEYS[1], ARGV[2], 1); " +// 2、设置 key 和 field, 并将 value 的值设置为 1"redis.call('pexpire', KEYS[1], ARGV[1]); " +// 3、设置 key 的过期时间"return nil; " +// 4、返回 null"end; " +"if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +// 5、如果 Redis 中存在对应的 key 和 field"redis.call('hincrby', KEYS[1], ARGV[2], 1); " +// 6、则将对应的 key 和 field 对应的 value 自增 1"redis.call('pexpire', KEYS[1], ARGV[1]); " +// 7、设置 key 的过期时间"return nil; " +// 8、返回 null"end; " +"return redis.call('pttl', KEYS[1]);",// 9、返回剩余生存时间, 单位毫秒// 以下这三个参数分别对应 Lua 脚本中的 KEYS[1], ARGV[1], ARGV[2]Collections.<Object>singletonList(getName()), internalLockLeaseTime, getLockName(threadId));}
复制代码Redisson 中实际加锁的代码 , 流程总结:
- 如果 Redis 中不存在 key 。
- 则使用 hset 这个命令设置 key 和 field , 并将 hash 的 value 设置为 1 , 这里使用 Redis 中的 hash 数据结构 , value 的值用于支持可重入锁 , 记录加锁次数 。
- 设置 key 的过期时间 。
- 加锁成功返回 null 。
- 如果 Redis 中存在对应的 key 和 field 。
- 将对应的 key 和 field 对应的 value 值自增 1 , 记录重入锁的次数 。
- 设置 key 的过期时间 。
- 加锁成功返回 null 。
- 加锁失败 , 返回 key 的剩余生存时间(单位毫秒) 。
锁自动续期代码解析:
推荐阅读
- 开一家豆制品加工厂,豆制品加工厂连锁加盟-
- 怎样开一家便利超市,便利店怎么开连锁-
- 《摩尔庄园》畜棚怎么解锁?
- 可爱手机壁纸 何同学时间锁壁纸高清2021最新
- 锁骨上长了个硬疙瘩
- 锁骨肌肉怎么练
- 玉雕|爱与守护,一个都不落,原来玉锁还能这样戴
- 锁阳粥的功效与作用
- 运动|从130斤瘦成锁骨精,张歆艺的下颌线像刀子,减肥最真实的明星
- 明朝也是闭关锁国吗,明朝闭关锁国和清朝闭关锁国-