tryLock→Redisson.tryLockAsync获取当前线程ID,默认无参数的trylock方法
会默认赋值waittime=-1(重试最大等待时间),leaseTime=-1存活时间,时间类型=null,线程ID=当前线程ID
→Redisson.tryAcquireOnceAsync
![](https://i-blog.csdnimg.cn/blog_migrate/866b810d691057311b2ec09102767b92.png)
leaseTime默认值等于-1,走
![](https://i-blog.csdnimg.cn/blog_migrate/0c6664abf2dc7ac661ad7d6aacbccd43.png)
方法,this.commandExecutor.getConnectionManager().getCfg().getLockWatchdogTimeout()默认为30秒
参数waitTime=-1,leaseTime=30秒,Time.unit为毫秒TimeUnit.MILLISECONDS,线程ID,redis命令(不知道干什么用)
tryLockInnerAsync执行Lua脚本
if (redis.call('exists', KEYS[1]) == 0)
判断key值是否存在,如果不存在
redis.call('hincrby', KEYS[1], ARGV[2], 1) 存入key值
redis.call('pexpire', KEYS[1], ARGV[1]) 设置存活时间
return nil; end 返回结束
如果key值存在
if (redis.call('hexists', KEYS[1], ARGV[2]) == 1)判断当前锁持有者是否是自己
如果是自己
"redis.call('hincrby', KEYS[1], ARGV[2], 1); hashkey中的value +1
同时更新持续时间
redis.call('pexpire', KEYS[1], ARGV[1]);
return nil; end 返回结束
如果持有锁的人不是自己,直接返回0;
public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
//时间毫秒化
long time = unit.toMillis(waitTime);
long current = System.currentTimeMillis();
long threadId = Thread.currentThread().getId();
//第一次尝试获取锁
Long ttl = this.tryAcquire(waitTime, leaseTime, unit, threadId);
//如果剩余时间为Null 证明已经获取到锁 直接返回
if (ttl == null) {
return true;
} else {
// 先用得到第一次尝试获取锁消耗的时间,然后用最大尝试时间减去得到剩余时间
time -= System.currentTimeMillis() - current;
//如果剩余时间小于0 证明超时,直接返回获取锁失败
if (time <= 0L) {
this.acquireFailed(waitTime, unit, threadId);
return false;
} else {
//再次获取当前时间
current = System.currentTimeMillis();
//订阅该线程ID释放锁的消息
//需要注意,当线程第一次获取锁失败后,并非立即发起请求,而是等待已经获取锁成功的线程执行完毕后释放锁,
//然后再次发起获取线程请求,故当第一次释放锁成功后的Lua脚本中有publish发布锁已释放的动作
//此时,当前线程已订阅部分,才会根据接收到释放消息去再次发起请求。
RFuture<RedissonLockEntry> subscribeFuture = this.subscribe(threadId);
//如果在剩余时间内没有接收到锁释放的消息,直接返回获取锁失败,同时取消订阅
if (!subscribeFuture.await(time, TimeUnit.MILLISECONDS)) {
if (!subscribeFuture.cancel(false)) {
subscribeFuture.onComplete((res, e) -> {
if (e == null) {
this.unsubscribe(subscribeFuture, threadId);
}
});
}
this.acquireFailed(waitTime, unit, threadId);
return false;
} else {
//收到锁释放消息,准备重新发起请求
try {
//再次计算剩余时间
time -= System.currentTimeMillis() - current;
if (time <= 0L) {
//时间小于0 返回获取锁失败
this.acquireFailed(waitTime, unit, threadId);
boolean var20 = false;
return var20;
} else {
//准备发起请求
boolean var16;
do {
long currentTime = System.currentTimeMillis();
ttl = this.tryAcquire(waitTime, leaseTime, unit, threadId);
if (ttl == null) {
//获取锁成功
var16 = true;
return var16;
}
//再次计算剩余时间
time -= System.currentTimeMillis() - currentTime;
if (time <= 0L) {
//剩余时间为0 返回错误
this.acquireFailed(waitTime, unit, threadId);
var16 = false;
return var16;
}
currentTime = System.currentTimeMillis();
//判断key值剩余存活时间与当前time剩余时间 ,然后根据信号量的方案,在释放锁释放信号的时候发起请求
//注:有最大尝试时间,
//如果ttl即key值存活时间较少则最大尝试时间为锁的剩余存活时间
//如果time时间较少,则最大尝试时间为time
//第一种情况ttl较少 当ttl过期证明key已过期,没有再尝试的必要
//第二种情况time较少 证明已经超过重试时间,应该返回失败
//通过信号量的方式阻塞锁定当前,直至以获取到锁的线程释放锁,接收到信息后再继续向下执行代码
if (ttl >= 0L && ttl < time) {
((RedissonLockEntry)subscribeFuture.getNow()).getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);
} else {
((RedissonLockEntry)subscribeFuture.getNow()).getLatch().tryAcquire(time, TimeUnit.MILLISECONDS);
}
//计算消耗时间
//如果是因为锁释放了,证明还有剩余时间,进行判断 ,剩余时间内再次发起获取锁的请求
time -= System.currentTimeMillis() - currentTime;
} while(time > 0L);
this.acquireFailed(waitTime, unit, threadId);
var16 = false;
return var16;
}
} finally {
this.unsubscribe(subscribeFuture, threadId);
}
}
}
}
}