한양과학기술고등학교

에듀테크 프로젝트 대시보드

데드락 (Deadlock)

서로가 서로를 기다리다 영원히 멈춰버리는 순간

데드락(교착 상태)은 둘 이상의 작업이 서로가 가진 자원을 기다리며, 아무도 앞으로 나아가지 못하는 상태다. 각자는 "상대가 놓아주면 계속하겠다"라고 버티지만, 상대도 똑같이 버티기 때문에 프로그램이 통째로 얼어붙는다. 아래 식사하는 철학자 시뮬레이터로 데드락이 생기는 과정과 이를 피하는 방법을 직접 눈으로 확인해 보자.

1 데드락이 생기는 네 가지 조건 (Coffman conditions)

아래 4가지가 동시에 성립할 때만 데드락이 발생할 수 있다. 하나라도 깨면 데드락은 원천적으로 불가능해진다 — 그래서 해결책은 대부분 이 중 하나를 무너뜨린다.

상호 배제 mutual exclusion

자원은 한 번에 한 작업만 쓸 수 있다. (포크 하나를 두 명이 동시에 못 든다)

점유하고 대기 hold & wait

자원을 이미 쥔 채로, 다른 자원을 추가로 기다린다. (왼쪽 포크를 든 채 오른쪽 포크를 기다림)

비선점 no preemption

남이 쥔 자원을 강제로 뺏을 수 없다. 주인이 스스로 놓아줄 때까지 기다려야 한다.

순환 대기 circular wait

대기 관계가 원을 그린다. A→B→C→…→A 처럼 서로 꼬리를 물고 기다린다.

2 식사하는 철학자 시뮬레이터
철학자 5명이 원탁에 앉아 있고, 사람 사이마다 포크가 1개씩 총 5개 있다. 한 명이 밥을 먹으려면 양옆 포크 2개가 모두 필요하다. 버튼을 눌러 실행해 보자.
식사 완료 횟수: 0
# 순진한 방식 — 데드락 가능 def philosopher(i): while True: think() fork[i].acquire() # 왼쪽 포크 fork[(i + 1) % 5].acquire() # 오른쪽 포크 ← 모두가 여기서 멈추면 데드락 eat() fork[i].release() fork[(i + 1) % 5].release() # 해결: 항상 "번호가 낮은 포크"를 먼저 집는다 → 순환 대기가 깨짐 def philosopher(i): a, b = sorted([i, (i + 1) % 5]) fork[a].acquire() fork[b].acquire() eat() fork[b].release(); fork[a].release()
3 데드락에 대처하는 4가지 전략

예방 (Prevention)

Coffman 조건 중 하나를 설계 단계에서 아예 못 만들게 한다. 예: 자원에 번호를 매기고 항상 오름차순으로만 요청 → 순환 대기 제거.

회피 (Avoidance)

자원을 줄 때마다 "이걸 주면 안전한 상태가 유지되나?"를 검사한다. 은행원 알고리즘이 대표적. 미래 최대 요청량을 미리 알아야 해서 실무엔 잘 안 쓴다.

탐지 & 복구 (Detection)

일단 데드락을 허용하되, 주기적으로 대기 그래프에 사이클이 있는지 검사한다. 발견하면 한 작업을 강제 종료(희생자 선택)하거나 롤백한다. DBMS가 이 방식을 쓴다.

무시 (Ostrich)

"거의 안 생기니 그냥 무시하고, 생기면 재부팅." 일반 운영체제(Linux·Windows)의 현실적인 선택이다. 타조가 머리를 모래에 묻는 것에 빗대어 부른다.

4 자주 나오는 질문
💡 데드락과 '기아(starvation)'는 뭐가 다른가?

데드락은 관련된 작업들이 전부 멈춘 채 영원히 진행되지 않는다. 기아는 시스템 전체는 돌아가는데 특정 작업만 계속 자원 우선순위에서 밀려 순서가 안 오는 상태다. 기아는 우선순위 에이징(오래 기다릴수록 우선순위를 올려줌)으로 완화한다.

💡 락을 하나만 쓰면 데드락이 안 생기나?

맞다. 데드락은 둘 이상의 락을 서로 다른 순서로 잡을 때 생긴다. 락이 하나뿐이면 순환 대기가 만들어질 수 없다. 그래서 실무 규칙은 "여러 락은 항상 같은 순서로 획득하라"이다. 이것만 지켜도 대부분의 데드락이 사라진다.

💡 데이터베이스에서도 데드락이 나나?

자주 난다. 트랜잭션 A가 row 1을 잠그고 row 2를 기다리는데, 트랜잭션 B가 row 2를 잠그고 row 1을 기다리면 교착이다. 대부분의 DBMS는 데드락 탐지기를 내장해 사이클을 감지하면 한 트랜잭션을 자동으로 롤백시키고 에러(deadlock detected)를 돌려준다. 앱은 그걸 잡아 재시도하면 된다.

💡 식사하는 철학자에서 "모두 오른쪽부터"로 바꾸면 안 되나?

안 된다. 방향만 반대일 뿐 여전히 모두 같은 방향이라 순환 대기가 그대로 생긴다. 핵심은 대칭을 깨는 것이다. 한 명만 반대 순서로 집게 하거나(비대칭), 포크에 번호를 매겨 낮은 번호부터 집게 하거나, 동시에 식탁에 앉는 인원을 4명으로 제한하면(자원 개수 제한) 해결된다.