쿠폰 발급 기능에서 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
이 발생할 수 있으므로 이를 적절히 처리한다.