
쿠폰 발급 기능에서 Redisson RedLock을 활용해 동시성 제어를 구현했다. 락 해제 시 중복 해제를 방지하기 위해 isHeldByCurrentThread()를 사용했지만, RedissonMultiLock에서 UnsupportedOperationException 예외가 발생했다.
RedissonMultiLock 특성
isHeldByCurrentThread() 메서드를 지원하지 않는다.isHeldByCurrentThread() 호출 시 문제
isHeldByCurrentThread()는 RedissonLock에는 존재하지만, RedissonMultiLock에서는 지원되지 않는다. UnsupportedOperationException 예외가 발생한다. 발생한 코드
if (redLock.isHeldByCurrentThread()) {
redLock.unlock();
}
예외 로그
java.lang.UnsupportedOperationException: null
at org.redisson.RedissonMultiLock.isHeldByCurrentThread(RedissonMultiLock.java:490)
핵심 전략:
RedissonMultiLock에서는 isHeldByCurrentThread()를 사용하지 말고,
트랜잭션 종료 시점에 unlock()만 호출하도록 한다.
최종 코드
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCompletion(int status) {
try {
redLock.unlock(); // 바로 unlock 호출
System.out.println("Thread " + Thread.currentThread().getId() + " released lock.");
} catch (IllegalMonitorStateException e) {
System.out.println("Lock already released or not held by thread.");
} catch (Exception e) {
System.err.println("Unexpected exception during lock release: " + e.getMessage());
}
}
});
포인트:
isHeldByCurrentThread() 검사를 제거한다. unlock() 호출 시 이미 해제된 락에 대한 예외(IllegalMonitorStateException)는 명확하게 처리한다.불필요한 검증 제거
isHeldByCurrentThread() 대신 트랜잭션 종료 시점에 unlock()만 호출한다.RedissonMultiLock 호환성 유지
RedissonMultiLock의 제한사항을 준수하면서도 안전하게 락을 해제한다.안정적인 예외 처리
unlock() 호출은 예외를 무시하도록 처리한다.RedissonMultiLock의 한계
isHeldByCurrentThread()는 RedissonLock 전용 메서드이며, RedissonMultiLock에서는 지원되지 않는다.중복 해제 방지 전략
unlock()을 호출해야 하며, 불필요한 검증 로직은 제거해야 한다.예외 처리
unlock() 호출 시 이미 해제된 락에 대해 IllegalMonitorStateException이 발생할 수 있으므로 이를 적절히 처리한다.