当前位置: 首页 > 科技观察

Redisson分布式锁公平锁排队加锁源码_0

时间:2023-03-18 15:04:40 科技观察

前言上一篇文章分析了公平锁加锁源码,总结:RedisHash数据结构:存储当前锁,RedisKey为锁,Hash的字段是锁定线程,Hash的值是重入次数;RedisList数据结构:充当线程等待队列,新的等待线程会使用rpush命令放在队列右侧;Redissortedset有序集数据结构:存储等待线程的顺序,score得分作为等待线程的超时时间戳。下面我们看一下线程是如何处理锁失败并被放入等待队列的。1排队等待锁源码入口:org.redisson.RedissonLock#lock(long,java.util.concurrent.TimeUnit,boolean)。线程进入队列后,会在Java代码中的while(true)循环中调用tryAcquire尝试获取锁。终于来到了RedissonFairLock#tryLockInnerAsync方法。为了方便,转贴Lua脚本和脚本参数的含义。KEYS[1]:锁名,anyLock;KEYS[2]:锁等待队列,redisson_lock_queue:{anyLock};KEYS[3]:设置等待队列中线程锁时间的集合,redisson_lock_timeout:{anyLock},是根据锁时间戳存入集合;ARGV[1]:locktimeouttime30000ARGV[2]:UUID:ThreadIdcombinationa3da2c83-b084-425c-a70f-5d9a08b37f31:1ARGV[3]:threadWaitTimedefault300000ARGV[4]:currentTime当前时间戳源码分析part1,while循环:从等待队列中获取第一个等待线程redisson_lock_queue:{anyLock};从等待线程超时集合中获取第一个等待线程的分数redisson_lock_timeout:{anyLock};如果没有超时,则直接结束,如果超时,则直接移除。第二部分,当前锁存在,直接跳过。第三部分,当前锁不是持锁线程,略过。第四部分直接返回当前锁多久过期。目前Redisson版本为3.15.6,不同版本略有不同。队列重排这里没有重排,因为官方认为这是一个bug,已经重新修复了。详情可以阅读:JustinCorpron2019/5/10,04:13FixtimeoutdriftinRedissonFairLock最大的变化是增加了第四部分。图片仅代表两个版本的差异,并不代表此版本有修改。2总结当线程获取锁失败进入等待队列时,ttl!=null,Java代码会继续尝试获取锁。当锁不存在,当前线程在等待队头时,直接获取锁。这个排队过程就是公平锁的退出。本文转载自微信公众号“程序员小航”,可通过以下二维码关注。转载本文请联系程序员小航公众号。