redissonClient.getlock()这个方法获取锁时,有几个问题没弄明白
1、锁一直被其他服务占用,但是因为redission存在看门口机制,会不断刷新锁的时间,导致锁一直被占用,此时其他线程getLock方法会怎么样?一直被阻塞嘛?还是到一定时间会自动抛出无法获取到锁?
2、此时如果原来的线程一直在运行,是不是当前锁会因为看门狗机制一直刷新过期时间,导致其他服务一直无法获取到锁?
本质在于我自己的加的锁,结果会被别的线程给删掉,对不对。
接下来我们能想到的办法就是给这个锁加一个唯一标志。把id加到锁里边去。
String uniqueId = UUID.randomUUID.toString() + threadId;
当我们要解锁的时候判断一下,加锁的id是否是我本人加的
String uniqueId = UUID.randomUUID.toString() + threadId;
try{
String lockKey = "lockKey";
Boolean result = redisTemplate.opsForValue().setIfAbsent(lockKey,uniqueId, "hello",10,TimeUnit.SECONDS);
if(!result){
return "something exception";
}
// 大量业务代码
...
}
finally{
if(uniqueId.equals(redisTemplate.opsForValue().get(lockKey))){
redisTemplate. delete(lockKey);
}
}
return "program End ...";
当执行到这儿,还是有点问题哈,如果程序执行15秒才结束,但是10秒锁才释放。还是会有并发的问题。
时间不是解决问题的方案,还有没有别的思路?
在redis的处理方式上确实有实现方法:在此现况的情景下,通过定时器去扫,分线程每过10秒扫一次,判断一下主线程是否持有锁,key是否还存在,如果存在,把超时时间再设置长一点,跟token续期类似。
根据参考资料中提到的内容,可以给出以下解答和优化建议:
redissonClient.getLock()
方法获取锁的其他线程会一直被阻塞,而不会自动抛出无法获取到锁的异常。因为Redisson中的分布式锁实现了看门狗机制,会定时刷新锁的过期时间。所以其他线程会一直等待锁被释放,直到超过锁的过期时间才会放弃获取锁的尝试。为了避免其他线程一直阻塞,可以使用tryLock()
方法,设置一个获取锁的超时时间,超过该时间后如果仍然无法获取到锁,就可以进行其他处理。示例代码:
RLock lock = redissonClient.getLock("myLock");
boolean isLocked = lock.tryLock(10, TimeUnit.SECONDS);
if (isLocked) {
try {
// 执行业务逻辑
} finally {
lock.unlock();
}
} else {
// 锁获取超时的处理逻辑
}
示例代码:
RLock lock = redissonClient.getLock("myLock");
try {
lock.lock();
// 执行关键代码
// 释放锁
lock.unlock();
} finally {
lock.unlock();
}
优化建议: - 在创建锁对象时,可以使用配置的分布式锁定时是否自动续期,以避免锁过期时间不足导致并发问题。 - 对于需要长时间锁定的关键代码,可以考虑将锁的持有时间设置得更长,或者在关键代码执行前手动续期锁的过期时间。 - 如果允许其他服务能够获取到锁,可以在关键代码执行完后手动释放锁,而不是依赖看门狗机制自动释放锁。
注意:以上建议是根据参考资料中提到的Redission框架和RedLock算法给出的解决方案,具体的实现细节还需要根据具体情况和业务需求进行调整。如果需要更多详细的实现代码和配置信息,请提供相关环境和业务场景的详细信息。