데드락이 뭐고 왜 생기는지, 발생하는 4가지 조건과 예방/해결 방법을 자바 예시와 함께 정리했습니다.
데드락이란
두 개 이상의 스레드(또는 프로세스)가 서로가 가진 자원을 기다리느라, 아무도 진행하지 못하고 영원히 멈춰버리는 상태입니다.
java
// 스레드 A: lock1을 잡고 lock2를 기다림
synchronized (lock1) {
synchronized (lock2) { ... }
}
// 스레드 B: lock2를 잡고 lock1을 기다림
synchronized (lock2) {
synchronized (lock1) { ... }
}
A가 lock1을 잡은 채 lock2를 기다리는데, 마침 B가 lock2를 잡은 채 lock1을 기다리고 있으면 둘 다 영원히 풀리지 않습니다. 이게 데드락입니다.
발생하는 4가지 조건
아래 조건이 전부 동시에 성립해야 데드락이 발생합니다. 하나라도 깨면 데드락을 막을 수 있습니다.
- 상호 배제(Mutual Exclusion): 자원을 한 번에 하나의 스레드만 사용할 수 있음
- 점유와 대기(Hold and Wait): 자원을 하나 잡은 채로, 다른 자원을 추가로 기다림
- 비선점(No Preemption): 다른 스레드가 잡은 자원을 강제로 빼앗을 수 없음
- 순환 대기(Circular Wait): A는 B의 자원을, B는 A의 자원을 기다리는 식으로 원형으로 물려 있음
해결 방법
1) 자원 접근 순서를 통일한다 (순환 대기 조건 제거)
가장 실무적인 방법입니다. 모든 스레드가 lock1 → lock2 순서로만 자원을 잡도록 강제하면, 순환이 생길 수 없습니다.
java
// A, B 모두 항상 lock1을 먼저 잡도록 통일
synchronized (lock1) {
synchronized (lock2) { ... }
}
2) 자원을 기다리는 시간에 제한을 둔다 (점유와 대기 완화)
tryLock(timeout)처럼 일정 시간 안에 자원을 못 얻으면 포기하고 자기가 가진 자원도 풀어주게 합니다.
java
if (lock1.tryLock(1, TimeUnit.SECONDS)) {
try {
if (lock2.tryLock(1, TimeUnit.SECONDS)) {
try { /* 작업 */ } finally { lock2.unlock(); }
}
} finally {
lock1.unlock();
}
}
3) 하나의 락만 사용하도록 설계를 단순화한다
애초에 여러 자원을 동시에 잡을 일이 없게 임계 영역을 재설계하는 방법입니다. 가장 근본적이지만 구조 변경이 필요합니다.
마무리
데드락은 "서로가 서로를 기다리며 아무도 못 움직이는 상태"이고, 상호 배제·점유와 대기·비선점·순환 대기 네 조건이 모두 맞아야 발생합니다. 실무에서는 이 중 순환 대기를 없애는 것, 즉 자원을 잡는 순서를 항상 동일하게 맞추는 방법이 가장 흔히 쓰입니다.
'DEV > cs' 카테고리의 다른 글
| [CS] Call By Value vs Call By Reference 차이 (1) | 2026.09.19 |
|---|---|
| [CS] TCP vs UDP 비교 (0) | 2026.09.18 |
| [CS] JAVA 가비지 컬렉션(GC)이란 (0) | 2026.09.16 |
| [CS] JAVA 인터페이스 vs 추상클래스, 뭐가 다른가 (0) | 2026.09.15 |
| [CS] 객체지향과 절차지향 프로그래밍이란, 비교 (0) | 2026.09.14 |