我有一个Spring Boot应用程序,其中具有用于缓存的Hazelcast。 当多个实例与Hazelcast集群在一起时,我在解锁操作中遇到此异常:
java.lang.IllegalMonitorStateException: Current thread is not owner of the lock! -> Owner: 33ce48f8-dda3-471f-abae-994d25dcc030, thread ID: 55
at com.hazelcast.concurrent.lock.operations.UnlockOperation.unlock(UnlockOperation.java:75) ~[hazelcast-3.11.4.jar!/:3.11.4]
at com.hazelcast.concurrent.lock.operations.UnlockOperation.run(UnlockOperation.java:64) ~[hazelcast-3.11.4.jar!/:3.11.4]
at com.hazelcast.spi.Operation.call(Operation.java:170) ~[hazelcast-3.11.4.jar!/:3.11.4]
at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.call(OperationRunnerImpl.java:208) [hazelcast-3.11.4.jar!/:3.11.4]
at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:197) [hazelcast-3.11.4.jar!/:3.11.4]
at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:413) [hazelcast-3.11.4.jar!/:3.11.4]
at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:153) [hazelcast-3.11.4.jar!/:3.11.4]
at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:123) [hazelcast-3.11.4.jar!/:3.11.4]
at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.run(OperationThread.java:110) [hazelcast-3.11.4.jar!/:3.11.4]
这是我进行锁定和解锁操作的组件:
package com.companyname.service.servicename.job;
import com.hazelcast.core.ILock;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class UpdateRaceCacheJob {
@Scheduled(fixedDelay = 10000)
public void updateRaceCache() {
ILock lock = hazelcastInstance.getLock("race-lock");
try {
if (!lock.tryLock()) {
return;
}
// service calls
} finally {
lock.unlock();
}
}
}
当我将 lock.unlock(); 行替换为:
if (lock.isLockedByCurrentThread()) {
lock.unlock();
}
我从声纳得到警告: 沿此方法的所有执行路径解锁此锁。
谢谢!
答案 0 :(得分:2)
由于Hazelcast锁是分布式的,因此它们受到线程所有权的保护,因此只有锁定它的线程才能解锁。
在您的代码中,您使用tryLock
,它可能返回false
。但是,finally
块在任何情况下都会执行解锁操作。因此,每次您都无法获得锁(因为它已被集群中的其他线程锁定)时,您将尝试将其解锁并得到该异常。
使用lock.isLockedByCurrentThread()
检查所有权是一个好主意。