好久不见,各位友友们
我正在尝试创建一个基础设施,不同的机器通过 Redisson 获取共享锁。一旦获得锁,一些异步任务就完成了,最后,当我完成工作时,我通过当前正在运行的线程释放 Redisson 锁 - 但我收到以下错误
java.lang.IllegalMonitorStateException: attempt to unlock lock, not locked by current thread by node id: xxxxx thread-id: 57
所以,我明白那个意思,但是因为我要执行异步工作,所以我不能使用获取线程来执行释放。
我不应该使用 Redisson 锁吗?像这样的异步工作的最佳匹配是什么?
解决方案:
由于需要异步解锁,所以上锁时,将线程Id也记录下来
@Override
public ResultIf<String> match(Long orderId) {
log.info("ResourceServiceImpl.match input:{}", orderId);
String requestId = "";
RLock lock = null;
try {
// 获取登录用户信息
ActiveUser activeUser = userSysDao.getCurrentUser();
Assert.notNull(activeUser, "activeUser is null");
Assert.isTrue(activeUser.getUid() != 0, "userId is null");
// 尝试获取锁
lock = RedisLock.tryFairlock(buildKey(MATCH_LOCK, orderId + "", activeUser.getUid() + ""));
if (ObjectUtils.isEmpty(lock)) {
return ResultIf.FAIL("请重试!");
}
boolean locked = lock.isLocked();
if (locked) {
return ResultIf.SUCCESS("正在匹配,请稍后重试");
}
requestId = IdUtil.randomId();
Assert.isTrue(StringUtils.isNotEmpty(requestId), "requestId is null");
boolean flag = lock.tryLock(60 * 4, TimeUnit.SECONDS);
if (flag) {
// 向redis中存入当前requestId
StringBuilder redisValue = new StringBuilder();
redisValue.append(requestId);
redisValue.append(":");
redisValue.append(Thread.currentThread().getId());
redisTemplateUtils.set(buildKey(MATCH_CURRENT_REQUEST, orderId + "", activeUser.getUid() + ""), redisValue.toString());
// todo 业务代码
return ResultIf.SUCCESS(requestId, "查询成功");
}
return ResultIf.SUCCESS("正在匹配,请稍后重试");
} catch (Exception ex) {
log.error("ResourceServiceImpl.match error", ex);
return ResultIf.EXCEPTION(ex.getMessage());
}
}
解锁
private void releaseLock(String orderId, String userId) {
RLock lock = null;
long threadId = 0l;
try {
/**
* 2、释放分布式锁
*/
lock = RedisLock.tryFairlock(buildKey(MATCH_LOCK, orderId, userId));
if (!ObjectUtils.isEmpty(lock)) {
/**
* 3、删除redis中当前requestId数据
*/
Object requestObj = redisTemplateUtils.get(buildKey(MATCH_CURRENT_REQUEST, orderId, userId));
if (!ObjectUtils.isEmpty(requestObj)) {
String redisValue = String.valueOf(requestObj);
String[] split = redisValue.split(":");
if (split.length == 2) {
threadId = Long.valueOf(split[1]);
}
}
// 是否还是锁定状态
if (lock.isLocked()) {
log.info("matchOperateLog unlock begin!");
if (threadId != 0l) {
lock.unlockAsync(threadId);
boolean del = redisTemplateUtils.deleteKey(buildKey(MATCH_CURRENT_REQUEST, orderId, userId));
log.info("matchOperateLog deleteKey remove res {}", del);
} else {
lock.unlockAsync();
}
log.info("matchOperateLog unlock end!");
}
}
} catch (Exception e) {
log.error("release operation failed", e);
} finally {
if (!ObjectUtils.isEmpty(lock) && lock.isLocked() && threadId != 0l) {
lock.unlock();
log.info("matchOperateLog finally unlock !");
}
}
}