DistributedLock
DistributedLock copied to clipboard
运行过程中异常中断,锁超时时使用getset会出现争抢
if (isTimeExpired(currLockInfo.getExpires()))
运行过程中异常中断,redis中会有一条锁记录,当程序重新启动后,多个线程会争抢锁,导致锁异常。
LockInfo currLockInfo = LockInfo.fromString(currLockInfoJson);
// 竞争条件只可能出现在锁超时的情况, 因为如果没有超时, 线程发现锁并不是被自己持有, 线程就不会去动value
if (isTimeExpired(currLockInfo.getExpires())) {
// 锁超时了
LockInfo oldLockInfo = LockInfo.fromString(jedis.getSet(lockKey, newLockInfoJson));
if (oldLockInfo != null && isTimeExpired(oldLockInfo.getExpires())) {
// 成功获取到锁, 设置相关标识
logger.debug("{} get lock(new), lockInfo: {}", Thread.currentThread().getName(), newLockInfoJson);
locked = true;
return true;
}
} else {
// 锁未超时, 不会有竞争情况
if (isHeldByCurrentThread(currLockInfo)) { // 当前线程持有
// 成功获取到锁, 设置相关标识
currLockInfo.setExpires(serverTimeMillis() + lockExpires + 1); // 设置新的锁超时时间
currLockInfo.incCount();
jedis.set(lockKey, currLockInfo.toString());
logger.debug("{} get lock(inc), lockInfo: {}", Thread.currentThread().getName(), currLockInfo);
locked = true;
return true;
}
}
过期的时候 getSet 会被最后一个执行的线程覆盖.很严重的错误.慎用