데드락(Deadlock)이란? 발생 조건과 4가지 해결 방법 완벽 정리
프로그램이 갑자기 멈추거나 시스템이 응답하지 않는 경험을 해본 적 있으신가요? 이런 현상의 원인 중 하나가 바로 데드락(Deadlock)입니다. 특히 멀티스레딩 환경이나 데이터베이스를 다루는 개발자라면 반드시 이해해야 할 핵심 개념인데요. 오늘은 데드락의 정의부터 발생 조건, 그리고 실무에서 활용할 수 있는 해결 방법까지 상세하게 알아보겠습니다.
데드락(Deadlock)의 정의와 기본 개념
데드락은 한국어로 교착 상태라고 번역되며, 두 개 이상의 프로세스나 스레드가 서로 상대방이 점유한 자원을 기다리면서 무한히 대기하는 상태를 의미합니다. 쉽게 말해 A가 B를 기다리고, B가 A를 기다리는 상황에서 아무도 진행할 수 없는 상태가 바로 데드락입니다.
일상생활에서 비유하자면, 좁은 골목에서 두 자동차가 마주쳤을 때 서로 비켜주지 않고 상대방이 먼저 비켜주길 기다리는 상황과 같습니다. 이 상태가 해결되지 않으면 두 차 모두 영원히 움직일 수 없게 됩니다.
컴퓨터 과학에서 데드락은 멀티프로그래밍 환경, 병렬 프로그래밍, 분산 컴퓨팅에서 흔히 발생하는 문제입니다. 한정된 시스템 자원을 여러 프로세스가 동시에 사용하려 할 때, 적절한 자원 관리가 이루어지지 않으면 데드락이 발생할 수 있습니다.
• • •
📌 관련 글
데드락 발생의 4가지 필수 조건 (코프만 조건)
1971년 코프만(Coffman) 교수가 정립한 이론에 따르면, 데드락이 발생하려면 다음 4가지 조건이 동시에 충족되어야 합니다. 이를 코프만 조건(Coffman Conditions)이라고 부르며, 하나라도 만족하지 않으면 데드락은 발생하지 않습니다.
상호 배제 (Mutual Exclusion)
자원은 한 번에 하나의 프로세스만 사용할 수 있습니다. 예를 들어 프린터나 특정 파일에 대한 쓰기 권한처럼, 동시에 여러 프로세스가 접근하면 문제가 생기는 자원들이 이에 해당합니다. 사용 중인 자원을 다른 프로세스가 사용하려면 해당 자원이 해제될 때까지 기다려야 합니다.
점유와 대기 (Hold and Wait)
프로세스가 최소한 하나의 자원을 점유한 상태에서 다른 프로세스가 사용 중인 자원을 추가로 얻기 위해 대기하는 상황입니다. 자원을 이미 보유하고 있으면서 동시에 다른 자원을 요청하는 상태가 데드락의 조건이 됩니다.
비선점 (No Preemption)
다른 프로세스에 할당된 자원은 해당 프로세스가 작업을 완료하고 자발적으로 반환할 때까지 강제로 빼앗을 수 없습니다. 높은 우선순위의 프로세스라 하더라도 이미 할당된 자원을 선점할 수 없는 상황을 의미합니다.
순환 대기 (Circular Wait)
대기 프로세스들이 순환 형태로 자원을 기다리는 상황입니다. 프로세스 A는 프로세스 B가 점유한 자원을 기다리고, B는 C의 자원을, C는 다시 A의 자원을 기다리는 식으로 대기 체인이 순환 구조를 형성합니다.
• • •
식사하는 철학자 문제로 이해하는 데드락
데드락을 설명할 때 가장 유명한 예시는 1965년 에츠허르 다익스트라(Edsger Dijkstra)가 만든 식사하는 철학자 문제(Dining Philosophers Problem)입니다. 이 문제는 동시성과 교착 상태를 직관적으로 이해할 수 있게 해줍니다.
다섯 명의 철학자가 원탁에 앉아 있고, 각자 앞에는 스파게티가 있으며 양옆에 포크가 하나씩 놓여 있습니다. 철학자가 식사를 하려면 양쪽 포크를 모두 집어야 합니다. 만약 모든 철학자가 동시에 왼쪽 포크를 집으면 어떻게 될까요?
모든 철학자가 왼쪽 포크를 들고 오른쪽 포크를 기다리지만, 오른쪽 포크는 이미 옆 사람이 왼쪽 포크로 집은 상태입니다. 결국 다섯 명 모두 서로의 포크를 기다리며 무한정 대기하게 되는데, 이것이 바로 교착 상태입니다. 이 문제는 운영체제에서 프로세스들이 자원을 두고 경쟁할 때 발생할 수 있는 데드락 상황을 완벽하게 보여줍니다.
• • •
데드락 해결 방법 4가지
데드락을 해결하는 방법은 크게 예방(Prevention), 회피(Avoidance), 탐지(Detection), 회복(Recovery)의 4가지로 분류됩니다. 각 방법의 특징과 장단점을 살펴보겠습니다.
1. 예방 (Prevention)
데드락 발생 조건 4가지 중 하나 이상을 원천적으로 제거하여 데드락 자체가 발생하지 않도록 방지하는 방법입니다.
상호 배제 부정은 여러 프로세스가 공유 자원을 동시에 사용할 수 있게 하는 것이지만, 이는 동기화 문제를 야기할 수 있어 실제 적용이 어렵습니다. 점유 대기 부정은 프로세스가 실행 전 필요한 모든 자원을 한꺼번에 요청하고 할당받는 방식입니다. 비선점 부정은 자원을 점유 중인 프로세스가 다른 자원을 요구할 때 기존 자원을 반납하도록 강제합니다. 순환 대기 부정은 자원에 고유 번호를 할당하고 정해진 순서대로만 자원을 요구하도록 제한합니다.
예방 방식은 구현이 비교적 단순하지만, 자원 사용 효율이 떨어지고 시스템 처리량이 감소하는 단점이 있습니다.
2. 회피 (Avoidance)
데드락 발생 가능성을 인정하면서도 자원 할당 전에 시스템이 안전한 상태를 유지할 수 있는지 미리 검사하여 데드락을 피하는 방법입니다. 대표적인 알고리즘으로 은행원 알고리즘(Banker's Algorithm)이 있습니다.
은행원 알고리즘은 다익스트라가 제안한 기법으로, 자원 할당 전에 모든 자원의 최대 가능 할당량을 시뮬레이션하여 시스템이 안전 상태(Safe State)를 유지할 수 있는지 검사합니다. 안전 순서열(Safe Sequence)이 존재하면 자원을 할당하고, 그렇지 않으면 요청을 거부합니다. 자세한 알고리즘 원리는 위키백과 교착 상태 문서에서 확인할 수 있습니다.
다만 은행원 알고리즘은 미리 최대 자원 요구량을 알아야 하고, 사용 가능한 자원 수가 일정해야 하는 등 제약 조건이 많습니다.
3. 탐지 (Detection)
데드락 발생을 허용하되, 주기적으로 시스템을 검사하여 데드락이 발생했는지 탐지하는 방법입니다. 자원 할당 그래프 알고리즘(Resource-Allocation Graph Algorithm)이나 Wait-for Graph를 통해 순환 대기 상태를 감지합니다.
탐지 알고리즘을 자주 실행하면 데드락을 빠르게 발견할 수 있지만, 그만큼 시스템 오버헤드가 증가합니다. 따라서 적절한 탐지 주기를 설정하는 것이 중요합니다.
4. 회복 (Recovery)
탐지 기법으로 데드락을 발견했다면 이를 해결하여 정상 상태로 복구해야 합니다. 회복 방법에는 프로세스 종료 방식과 자원 선점 방식이 있습니다.
프로세스 종료 방식은 교착 상태에 있는 프로세스를 모두 중단하거나, 하나씩 중단시키면서 데드락이 해소되는지 확인합니다. 자원 선점 방식은 우선순위가 낮거나 수행 횟수가 적은 프로세스의 자원을 강제로 빼앗아 다른 프로세스에 할당합니다. 극단적인 경우에는 데드락 발생 전 상태로 롤백(Rollback)하기도 합니다.
• • •
데이터베이스에서의 데드락
데드락은 운영체제뿐만 아니라 데이터베이스 환경에서도 빈번하게 발생합니다. 데이터베이스에서는 여러 트랜잭션이 동시에 실행될 때 각각 Lock을 획득한 상태에서 서로의 Lock을 요구하면 데드락이 발생할 수 있습니다.
MySQL InnoDB 엔진의 경우, 데드락이 발생하면 자동으로 데드락 그래프를 분석하여 관련 트랜잭션 중 하나를 롤백시킵니다. SHOW ENGINE INNODB STATUS 명령어를 통해 데드락 발생 내역과 관련된 트랜잭션 정보를 확인할 수 있습니다.
데이터베이스 데드락을 예방하려면 트랜잭션을 가능한 짧게 유지하고, 모든 코드가 동일한 순서로 테이블과 행에 접근하도록 설계해야 합니다. 또한 적절한 인덱스 설정으로 Lock이 걸리는 범위를 최소화하고, 외래키로 인한 잠금 전파에 주의해야 합니다.
• • •
데드락 발생 조건과 해결 방법 비교
| 구분 | 내용 |
|---|---|
| 상호 배제 | 한 자원은 한 번에 하나의 프로세스만 사용 가능 |
| 점유와 대기 | 자원을 보유한 상태에서 다른 자원 대기 |
| 비선점 | 할당된 자원을 강제로 빼앗을 수 없음 |
| 순환 대기 | 프로세스들이 순환 형태로 자원 대기 |
| 예방 | 4가지 조건 중 하나를 제거하여 원천 차단 |
| 회피 | 은행원 알고리즘으로 안전 상태 유지 |
| 탐지 | 그래프 알고리즘으로 데드락 발생 감지 |
| 회복 | 프로세스 종료 또는 자원 선점으로 복구 |
• • •
✅ 꼭 알아두세요
- 데드락은 4가지 조건이 모두 충족될 때만 발생합니다: 하나라도 제거하면 데드락을 예방할 수 있습니다.
- 실무에서는 탐지와 회복 방식이 많이 사용됩니다: 예방과 회피는 시스템 효율을 떨어뜨릴 수 있어 데드락 발생 확률이 낮은 경우 별도 조치를 하지 않기도 합니다.
- DB 데드락은 대부분 자동 해결됩니다: MySQL, Oracle 등 현대 DBMS는 데드락을 자동 탐지하고 한쪽 트랜잭션을 롤백합니다.
- 코드 설계 시 자원 접근 순서를 통일하세요: 모든 트랜잭션이 동일한 순서로 자원에 접근하면 순환 대기를 방지할 수 있습니다.
• • •
📖 함께 읽으면 좋은 글
- 퇴직연금대출 조건과 신청 방법 총정리|담보대출 vs 중도인출 비교
- 서울시청 노인일자리센터 | 면접 팁 | 취업성공사례 | 사회복지사 채용 | 업무 절차 | 창업 아이템 | 급여 계산법
- 광주 다이소 알바 급여 안내 | 월급 계산과 지급일
자주 묻는 질문 (FAQ)
Q. 데드락과 병목 현상의 차이점은 무엇인가요?
A. 병목 현상은 여러 구성 요소가 동시에 실행될 때 가장 느린 쪽의 속도에 맞춰 전체 시스템이 느려지는 현상입니다. 반면 데드락은 서로 상대방의 자원을 기다리며 완전히 멈춰버리는 상태입니다. 병목 현상은 느리지만 진행은 되고, 데드락은 아예 진행이 불가능합니다.
Q. 데드락이 발생하면 프로그램이 완전히 멈추나요?
A. 데드락에 관련된 프로세스나 스레드만 멈추고, 그 외의 부분은 정상 작동할 수 있습니다. 다만 데드락에 빠진 자원이 시스템 핵심 자원이라면 전체 시스템에 영향을 줄 수 있습니다. 대부분의 현대 운영체제와 DBMS는 데드락을 탐지하고 자동으로 해결하는 기능을 제공합니다.
Q. 데드락을 완전히 없앨 수 있는 방법이 있나요?
A. 이론적으로는 데드락 발생 조건 4가지 중 하나를 제거하면 데드락을 완전히 예방할 수 있습니다. 하지만 실제로는 자원 효율성 저하, 구현 복잡도 증가 등의 문제가 있어 완벽한 예방보다는 탐지 후 회복하는 방식이 많이 사용됩니다. 특히 차량이나 항공기 시스템처럼 안정성이 중요한 환경에서는 예방 기법을 적극 활용합니다.
• • •
마치며
데드락은 멀티프로그래밍 환경에서 필연적으로 마주할 수 있는 문제입니다. 상호 배제, 점유와 대기, 비선점, 순환 대기라는 4가지 조건을 이해하고, 상황에 맞는 해결 방법을 적용하는 것이 중요합니다. 특히 데이터베이스를 다루는 개발자라면 트랜잭션 설계 시 데드락 가능성을 항상 고려하여 안정적인 시스템을 구축하시기 바랍니다.