文章目录
- redission 加锁代码-有问题
- 优化代码
- 看门狗是什么?
redission 加锁代码-有问题
/**
* 收货入库物料标签(包装码)推送接口
*
* @throws Exception
*/
public void synReceiveMaterialTags() throws Exception {
String tag = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
String key = RedisKeyPre.synReceiveMaterialTagsLock;
RLock rLock = redissonClient.getLock(key);
try {
// 尝试加锁,最多等待3秒,上锁以后1200秒自动解锁,没有Watch Dog,1200s后自动释放
boolean res = rLock.tryLock(3, 1200, TimeUnit.SECONDS);
if (!res) {
Log.info(LogBuilder.builder().business("synReceiveMaterialTags:" + tag + ":获取锁失败,稍后重试").build());
return;
} else {
wmsSyncService.synReceiveMaterialTags();
}
} catch (Exception e) {
Log.error(LogBuilder.builder().business("synReceiveMaterialTags error:" + e).build());
} finally {
releaseLock(rLock);
}
}
private void releaseLock(RLock rLock) {
if (rLock.isLocked() && rLock.isHeldByCurrentThread()) {
rLock.unlock();
}
}
rLock.tryLock(3, 1200, TimeUnit.SECONDS)表示尝试获取锁,最多等待3秒,锁的持有时间为1200秒(20分钟),超过持有时间后锁会自动释放。这样可以避免锁被长时间占用,提高代码的健壮性和性能。
如果不需要等待时间和自动释放时间,可以将tryLock()方法的参数调整为rLock.tryLock(),这样会立即尝试获取锁,如果锁不可用,则立即返回结果。但是需要注意,这样可能会导致线程频繁尝试获取锁,增加系统负载和竞争,需要根据具体情况进行评估和调整。
优化代码
这段代码存在一些问题:
-
异常处理不够详细:在synReceiveMaterialTags方法中,捕获了异常并记录了错误日志,但没有对异常进行具体的处理。建议根据实际情况,对异常进行适当的处理,例如回滚事务、发送通知等。
-
锁的释放方式不正确:在releaseLock方法中,使用isLocked和isHeldByCurrentThread方法来判断锁是否被当前线程持有,并进行解锁操作。然而,这种方式可能存在并发问题,因为在判断锁状态和解锁之间,其他线程可能已经获取了锁并修改了锁状态。建议使用try-finally语句来确保锁的正确释放,无论是否发生异常。
-
日志记录不规范:在日志记录中,使用了字符串拼接的方式来构建日志信息。建议使用日志框架,如Log4j或Slf4j,来记录日志,并使用占位符或参数化日志的方式,以提高性能和可读性。
优化后的代码示例:
public void synReceiveMaterialTags() {
String tag = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
String key = RedisKeyPre.synReceiveMaterialTagsLock;
RLock rLock = redissonClient.getLock(key);
try {
// 尝试加锁,最多等待3秒,上锁以后1200秒自动解锁,没有Watch Dog,1200s后自动释放
boolean res = rLock.tryLock(3, 1200, TimeUnit.SECONDS);
if (!res) {
Log.info("synReceiveMaterialTags:{}:获取锁失败,稍后重试", tag);
return;
} else {
wmsSyncService.synReceiveMaterialTags();
}
} catch (Exception e) {
Log.error("synReceiveMaterialTags error:{}", e);
// 异常处理逻辑
} finally {
try {
rLock.unlock();
} catch (IllegalStateException e) {}
// 锁已经
看门狗是什么?
在这段代码中,"没有Watch Dog"是指在加锁的过程中没有使用监视器(watchdog)来监控锁的状态。通常情况下,当一个线程获取了锁但在一定时间内没有释放锁时,监视器会检测到这种情况并自动释放锁,以防止死锁的发生。
在这段代码中,锁的超时时间设置为1200秒,但没有使用监视器来监控锁的状态。这意味着如果某个线程获取了锁后,在1200秒内没有释放锁,其他线程将无法获取到锁,可能会导致程序出现长时间的等待或阻塞。
为了避免这种情况,建议在加锁时使用监视器来监控锁的状态,并在一定时间内自动释放锁,以提高程序的健壮性和性能。