모든 스레드가 락을 동일한 순서로 확보하려 할 때 데드락이 발생할 수 있는데, 여기에서 락을 확보하는 순서는 전적으로 메소드를 호출하는 인자의 순서에 달렸다.
따라서 두 개의 스레드가 메소드를 동시에 호출하되, 한쪽 스레드는 X에서 Y로의, 다른 쪽 스레드는 Y에서 X로 호출될 때, 데드락이 발생한다.
public void transferMoney(Account fromAccount, Account toAccount, DollarAmount amout) {
synchronized (fromAccount) {
synchronized(toAccount) {
// ...
}
}
}
위와 같이 중첩된 구조에서 락을 가져가는 상황에서 데드락을 찾아낼 수 있다.
락을 확보하려는 순서를 내부적으로 제어할 수 없기 때문에 여기에서 데드락을 방지하려면 락을 특정 순서에 맞춰 확보하도록 해야 하고, 락을 확보하는 순서를 프로그램 전반적으로 동일하게 적용해야 한다.
자바에서의 예시
public void transferMoney(Account fromAccount, Account toAccount, DollarAmount amout) {
int fromHash = System.identityHashCode(fromAccount);
int toHash = System.identityHashCode(toAccount);
if(fromHash < toHash) {
synchronized (fromAccount) {
synchronized(toAccount) {
// ...
}
}
} else {
synchronized (toAccount) {
synchronized(fromAccount) {
// ...
}
}
}
}
자바에서 객체에 순서를 부여할 수 있는 방법 중에 하나는 System.identityHashCode
를 사용하는 방법인데, identityHashCode
메소드는 해당 객체의 Object.hashCode
메소드를 호출할 때의 값을 알려준다.
위의 코드는 identityHashCode
메소드를 활용해 구한 값을 기준으로 락의 순서를 동일하게 적용한 코드다.
'개발' 카테고리의 다른 글
네임드 락과 커밋 (0) | 2025.03.20 |
---|---|
블로킹 큐와 프로듀서-컨슈머 패턴 (0) | 2025.03.06 |
SQS 리스너 구현기 (0) | 2025.01.16 |
도메인 이벤트 모듈 구성 (0) | 2025.01.16 |
이벤트 모듈 설계 문서 (0) | 2025.01.14 |