백엔드 면접 용어 사전
운영체제교착 상태 · deadlock

데드락

서로가 쥔 자원을 기다려 아무도 진행하지 못하는 상태. 상호배제·점유대기·비선점·환형대기가 동시에 성립할 때 발생한다.

둘 이상의 작업이 서로가 가진 자원을 기다리며 영원히 멈추는 상태(교착 상태).

가장 단순한 형태

스레드 A: lock(1) 성공 → lock(2) 요청 → 대기 스레드 B: lock(2) 성공 → lock(1) 요청 → 대기

A는 B가 2를 놓기를, B는 A가 1을 놓기를 기다린다 → 영원히

성립 조건 네 가지 — 하나만 깨면 안 생긴다

조건깨는 방법
상호 배제자원을 동시에 못 씀공유 가능하게(읽기 전용, 불변 객체)
점유와 대기가진 채로 더 요구한 번에 다 잡거나, 못 잡으면 전부 놓기
비선점강제로 뺏을 수 없음타임아웃 후 포기
순환 대기대기가 원을 이룸자원에 순서를 매겨 그 순서로만 잡기

★ 네 번째를 깨는 것이 실무에서 가장 현실적이다.

// ❌ 위험 — 호출자에 따라 순서가 달라진다
void transfer(Account from, Account to) {
    synchronized (from) { synchronized (to) { … } }
}
// transfer(A, B)와 transfer(B, A)가 동시에 → 데드락

// ✅ id 순서로 고정 — 누가 부르든 항상 같은 순서
void transfer(Account a, Account b) {
    Account first = a.id < b.id ? a : b;
    Account second = a.id < b.id ? b : a;
    synchronized (first) { synchronized (second) { … } }
}

다루는 세 가지 전략

① 예방(prevention) — 위 네 조건 중 하나를 애초에 못 만들게 한다. 가장 실용적. ② 회피(avoidance) — 은행원 알고리즘. 자원 요청마다 안전한지 검사한다. 이론적으로 우아하지만 최대 요구량을 미리 알아야 해서 실무에선 거의 안 쓴다. ③ 탐지와 복구(detection) — 일단 두고, 주기적으로 대기 그래프에서 사이클을 찾아 하나를 강제 종료한다. DB가 쓰는 방식이다.

DB 데드락 — 실무에서 훨씬 자주 만난다

-- 트랜잭션 1
UPDATE account SET balance = balance - 100 WHERE id = 1;
UPDATE account SET balance = balance + 100 WHERE id = 2;

-- 트랜잭션 2 (동시에)
UPDATE account SET balance = balance - 50 WHERE id = 2;
UPDATE account SET balance = balance + 50 WHERE id = 1;

InnoDB는 대기 그래프에서 사이클을 감지해 비용이 적은 쪽을 롤백한다.

ERROR 1213: Deadlock found when trying to get lock; try restarting transaction

"try restarting transaction" — DB가 대놓고 재시도하라고 한다. 데드락은 완전히 없앨 수 없으므로 재시도 로직이 정답이다.

빈도를 줄이는 방법

  • 갱신 순서를 일관되게(id 오름차순)
  • 트랜잭션을 짧게
  • 인덱스를 잘 걸어 락 범위를 좁게 (인덱스가 없으면 넓게 잠겨 충돌↑)
  • 격리수준을 낮춰 갭 락을 줄이는 것도 선택지

진단

SHOW ENGINE INNODB STATUS;   -- LATEST DETECTED DEADLOCK 섹션

어떤 두 트랜잭션이 어떤 락을 두고 충돌했는지 SQL까지 나온다.

자바는 jstack <pid>"Found one Java-level deadlock" 을 직접 알려 준다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 운영체제 — 프로세스/스레드·동기화·가상메모리