Redisson有两个类,分别是RedissonMultiLock和RedsissonLock,都可以实现加锁,但是里面的实现逻辑有些差别
RedissonMultiLock
RedissonMultiLock可以指定等待时间,也就是说,假如我指定了等待时间是2S,比如:
1.A线程来加锁,正常去执行业务逻辑
2.B线程也来加锁,此时会加锁失败,那B线程最多等待2S,如果超过了2S还没有获取到分布式锁,那B线程加锁就返回false,表示加锁失败
加锁
RedissonMultiLock和RedissonRedLock有关系
而RedissonRedLock大致的思想是:在加锁的时候,Redis必须是集群配置,加锁的时候,会依次去多台Redis机器上进行加锁,如果一半以上的锁加锁成功了,就认为是加锁成功了,这个点我没有去看代码验证,只是先看了下加锁和解锁的部分细节
org.redisson.RedissonMultiLock#tryLock(long, long, java.util.concurrent.TimeUnit)
在加锁的时候,会调用到这个方法,这里入参的意思分别是:
第一个waitTime是锁等待时间
leaseTime是锁加锁时间
TimeUnit是时间单位
我的理解是:线程A在加锁的时候,会使用leaseTime作为锁失效时间,如果没有指定,就是默认30S,然后进行锁续期;如果指定了,那就使用指定的阈值,并且不会自动化续期
线程B来加锁的时候,如果线程A已经对同一个key进行了加锁,那线程B最多等待waitTime时间,如果到了这个时间,线程B依旧没有获取到锁,那线程B加锁的方法就会返回false,表示加锁失败
public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
long newLeaseTime = -1;
// 1.这里是在指定了超时时间的时候,会将新的超时时间设置为锁等待时间的2倍;这里我没怎么理解为什么要这么做
if (leaseTime != -1) {
newLeaseTime = unit.toMillis(waitTime)*2;
}
long time = System.currentTimeMillis();
long remainTime = -1;
// 2.如果waitTime不等于-1,就是指定了等待时间的场景下,将等待时间转换为毫秒
if (waitTime != -1) {
remainTime = unit.toMillis(waitTime);
}
// 3.这里的计算,会用remainTime / Redis机器的数量;所以:如果我指定的等待时间是2000ms,那这里获取到的lockWaitTime就是666ms
long lockWaitTime = calcLockWaitTime(remainTime);
int failedLocksLimit = failedLocksLimit();
List<RLock> acquiredLocks = new ArrayList<RLock>(locks.size());
// 4.对所有的Redis加锁机器进行遍历,然后依次去加锁,如果加锁失败的话,会进行一些列的处理;这里加锁失败的处理逻辑我还没有细看,后面再补充
for (ListIterator<RLock> iterator = locks.listIterator(); iterator.hasNext();) {
RLock lock = iterator.next();
boolean lockAcquired;
try {
// 4.1 如果等待时间未指定、锁超时时间未指定,那就调用下面这个方法即可
if (waitTime == -1 && leaseTime == -1) {
lockAcquired = lock.tryLock();
} else {
// 4.2 反之,就会调用入参了waitTime和leaseTime的方法
long awaitTime = Math.min(lockWaitTime, remainTime);
lockAcquired = lock.tryLock(awaitTime, newLeaseTime, TimeUnit.MILLISECONDS);
}
} catch (RedisResponseTimeoutException e) {
unlockInner(Arrays.asList(lock));
lockAcquired = false;
} catch (Exception e) {
lockAcquired = false;
}
if (lockAcquired) {
acquiredLocks.add(lock);
} else {
if (locks.size() - acquiredLocks.size() == failedLocksLimit()) {
break;
}
if (failedLocksLimit == 0) {
unlockInner(acquiredLocks);
if (waitTime == -1 && leaseTime == -1) {
return false;
}
failedLocksLimit = failedLocksLimit();
acquiredLocks.clear();
// reset iterator
while (iterator.hasPrevious()) {
iterator.previous();
}
} else {
failedLocksLimit--;
}
}