看门狗机制是分布在 RedissonBaseLock#scheduleExpirationRenewal 方法中,这块公平锁和非公平锁并无区别。式锁释放
前文已经了解到,源码公平锁加锁失败之后,平锁会将当前放到等待队列中,分布通过 Java 代码中的式锁释放循环不断尝试获得锁。
主动释放
源码:RedissonFairLock#unlockInnerAsync
KEYS[1]:加锁的源码名字,anyLock; KEYS[2]:加锁等待队列,平锁redisson_lock_queue:{ anyLock}; KEYS[3]:等待队列中线程锁时间的分布 set 集合,redisson_lock_timeout:{ anyLock},式锁释放是源码按照锁的时间戳存放到集合中的; KEYS[4]:redisson_lock__channel:{ anyLock}; ARGV[1]:LockPubSub.UNLOCK_MESSAGE; ARGV[2]:锁超时时间 30000; ARGV[3]:UUID:ThreadId 组合 58f6c4a2-9908-4957-b229-283a45359c4b:47; ARGV[4]:currentTime 当前时间戳。这块逻辑突出部分已经标出,平锁重点就是分布释放锁。
锁在队列中,式锁释放超时了则直接从队列中移除; 锁减少重入次数,源码减少后,高防服务器如果重入次数大于 0,重置超时时间,如果不大于 0,则直接移除锁。这样的话后续就其他线程从等待队列中开始获得锁。
超时删除
在加锁和释放锁的 lua 脚本中,第一段永远是一个 while true do xxx,作用就是用来移除队列中超时的锁。
而持锁线程的释放,则和非公平锁没有任何区别,当锁超时或者服务宕机,锁就会被自动释放。(这个是指 anyLock)。
公平锁的释放同样分为主动释放和超时释放。
主动释放,站群服务器即自己调用释放锁。
超时删除,则分为两种,一种是持锁线程超时删除,这种和非公平锁没有任何区别,因为这个锁也是含有超时时间+看门狗续租的。另一种则是等待队列中的超时删除,是在每次获取锁之前,判断第一个等待线程的时间戳是否超时,从而移除锁。
本文转载自微信公众号「程序员小航」,可以通过以下二维码关注。转载本文请联系程序员小航公众号。