변수의 기록

(OS) 데드락이란? (발생조건 , 해결방안 포함) 본문

CS지식/운영체제 (Operating System)

(OS) 데드락이란? (발생조건 , 해결방안 포함)

불광동 물주먹 2025. 4. 12. 23:02

  데드락(Deadlock) 정리 – 원인과 해결 방법

**데드락(교착 상태)**은 둘 이상의 프로세스나 스레드가 서로가 점유한 리소스를 기다리며 무한 대기하는 상태를 말합니다. 이런 상황은 시스템 자원을 병렬로 사용하는 환경에서 자주 발생할 수 있어, OS 수준의 제어가 필요합니다.

 

 

사진출처 -유튜브 쉬운코드

 

도로는 리소스 
차는 프로세스 

 

조건1.각 차들은 2개의 도로(숫자) 리소스를 가져야함.

가지려다가 두번쨰 사진처럼 교착상태를 마주하게 됨. 

 

이것이 데드락.

 

 

🧩 데드락 발생의 4가지 조건

데드락은 아래 4가지 조건이 모두 충족될 때 발생합니다. 하나라도 깨지면 데드락은 발생하지 않습니다.


 

조건 설명 예시
1. Mutual Exclusion (상호배제) 리소스는 하나의 프로세스만 점유 가능(공유x) 프린터, 락(lock)
2. Hold and Wait (점유 대기) 프로세스가 리소스를 점유(hold)한 상태에서 다른 리소스를 기다림(wait) 스레드 A가 lock(X)를 점유한 채, lock(Y)를 기다림.
3. No Preemption (비선점) 리소스를 점유한 프로세스만 반환(release) 가능 락은 소유자가 직접 해제
4. Circular Wait (순환 대기) 프로세스들이 원형으로 서로의 리소스를 기다림 P1 → P2 → P3 → P1 순환

💡 데드락 해결 방법 4가지

운영체제는 아래 네 가지 방식으로 데드락 문제를 대응합니다:


1️⃣ 데드락 방지 (Prevention)

애초에 4가지 조건 중 최소 하나라도 충족되지 않도록 설계합니다.

  • Mutual Exclusion 제거: 리소스를 공유 가능하게 설계 (사실상 어려움 – 레이스 컨디션 위험)
  • Hold and Wait 제거:

    * Hold and Wait 방지 방법에는 두 가지가 있다.
     모든 리소스를 한꺼번에 확보한 후 실행 (All-or-Nothing)
     이미 점유한 리소스를 반납하고 다시 전체를 요청  

    방식 설명 단점
    1. All-or-Nothing 필요한 모든 리소스를 한 번에 확보한 뒤 실행 시작 필요한 자원이 다 준비될 때까지 기약 없이 대기 → Starvation 발생 가능
    2. Release-and-Retry 추가 리소스가 필요하면 이미 가진 리소스를 모두 반납 후 다시 요청 계속 반납/재시도하며 진행이 늦어질 수 있음Starvation 발생 가능
    두 방식 모두 데드락을 예방할 수 있지만, 자원 활용률 저하와 무한 대기의 가능성이 있어 실무에서는 상황에 따라 선택한다.
  • No Preemption 제거
    • 추가적인 리소스를 기다려야 한다면 이미 획득한 리소스를 다른 프로세스가 선점 가능하도록 한다.
    • 예: 고우선순위 프로세스가 기존 리소스를 뺏을 수 있음 (context switch나 lock timeout 등)
        ex) cpu에서 컨텍스트 스위칭이랑 비슷함 (타임슬라이스 다 끝나면 다른 프로세스에게 양보함 .)
        ex) 모니터와도 비슷 lock 점유하고도 다음 작업시 대기해야할 시 lock 양보해주니깐. 
  • Circular Wait 제거:
    • 모든 리소스에 우선순위 부여
    • 리소스 반환(release)은 오직 리소스를 취득한 프로세스만 할 수 있음.
    • 오름차순으로만 요청하도록 제한 (예: DB → File → Printer 순)

 

📝 가장 실무에서 많이 사용되는 방식이 “순서 기반 요청( Circular Wait  )” 방식입니다.


2️⃣ 데드락 회피 (Avoidance)

데드락 가능성은 있으나, OS가 실행 중인 프로세스 상태와 리소스 상황을 분석해 회피

  • 대표 알고리즘: Banker’s Algorithm
    • 프로세스가 리소스를 요청했을 때, **데드락 없이 안전 상태(Safe State)**가 유지되는 경우에만 자원 할당
    • 미리 "최대 필요량(Max)" 정보 필요

3️⃣ 데드락 감지와 복구 (Detection & Recovery)

데드락을 허용하고, 발생 시 이를 감지하여 복구

  • 감지 방법: 리소스-프로세스의 대기 그래프(Resource Allocation Graph)를 이용한 사이클 탐지
  • 복구 방법
    • 프로세스 종료: 데드락에 포함된 프로세스를 종료 (하나씩 or 전체)
    • 리소스 선점: 일시적으로 자원을 강제로 회수하여 해소

🧨 비용이 크기 때문에 최후의 수단으로 사용


4️⃣ 데드락 무시 (Ignore)

  • 소규모 시스템에서 “개발자가 알아서 해결하겠지” 전략
  • 실제로 Unix, Linux 등의 OS에서는 이 방법이 기본(default)

🧪 실무에서는 이 방식이 많음 – 대신 개발자가 락 설계, 순서, timeout 등 신중하게 구성

 


자바에서 데드락 발생 예제와 해결 전략

다음은 자바에서 발생 가능한 데드락(Deadlock) 예시

 

 

사진 출처 - 유튜브 쉬운코드

 

✳️ 상황 설명

  • Thread t1은 lock1을 먼저 얻고 → 이후 lock2를 요청
  • Thread t2는 lock2를 먼저 얻고 → 이후 lock1을 요청
  • 이때 두 스레드는 서로가 가진 락을 기다리며 무한 대기 상태, 즉 데드락이 발생합니다.

t1 : lock(1) -> lock(2) 시도 (대기)
t2 : lock(2) -> lock(1) 시도 (대기)

 


✅ 데드락을 피하기 위한 설계 관점

1️⃣ 꼭 필요한 락인가? – Mutual Exclusion 재검토

  • synchronized 블록으로 **리소스를 독점(lock)**하고 있는데,
    이게 정말 경쟁이 필요한 자원인지 고민이 필요합니다.
    가능하다면, 락 자체를 없애거나 락 경합이 일어나지 않도록 분리된 구조 설계가 더 좋음

📌 실전 팁:

  • 상태 변경 없이 단순 읽기만 한다면 굳이 락 필요 없음
  • 락 범위를 좁히거나 읽기/쓰기 분리 전략도 고려 가능

2️⃣ 락 순서 고정 – Circular Wait 차단

  • 위 예제처럼 각 스레드가 서로 다른 순서로 락을 요청하면, 순환 대기(Circular Wait)가 발생합니다.
  • 이를 막기 위해 각 스레드는 리소스를 요청할 때, 시스템에서 정한 우선순위를 따르며 항상 낮은 순서 → 높은 순서대로만 요청해야 Circular Wait를 방지할 수 있다.

🛠 해결 방법 예:

// t2에서 synchronized(lock1) → synchronized(lock2) 순서로 변경

 


3️⃣ 중첩된 락 구조 꼭 필요한가? – Hold and Wait 고려

  • 현재 구조는 락을 하나 점유한 상태에서 다른 락을 중첩으로 획득하려 합니다. (nested synchronized)
  • 중첩이 정말 필요한 상황이 아니라면, 락을 해제하고 난 뒤 새로운 락을 획득하는 방식으로 설계하는 게 좋습니다.

📌 예: 중첩을 풀고, 각각의 synchronized 블록으로 분리

synchronized(lock1) {
    // 작업 1
}
synchronized(lock2) {
    // 작업 2
}
 

데드락 회피를 위한 개발자의 고민

  • 락은 정말 필요한가?
  • 락 순서를 고정할 수 있는가?
  • 중첩된 락을 단순화할 수 있는가?
  • 락 범위를 줄이고, 비동기 구조나 분산 처리를 도입할 수는 없을까?

데드락은 코드만 잘 짜서 피하는 게 아니라, 초기 설계 단계에서의 구조적 고민이 핵심이라는 생각이 듬
복잡한 동시성 환경일수록, 락 설계는 단순하고 명확해야 한다.

 

 

✅ 마무리 정리

 

구분 핵심  개념
데드락 정의 서로가 가진 리소스를 기다리며 무한 대기
발생 조건 상호배제, 점유대기, 비선점, 순환대기 (4가지 모두 필요)
해결 방법 방지, 회피, 감지 및 복구, 무시 (총 4가지 전략)
실무 팁 리소스 요청 순서 고정, 락 timeout 설정, 가능하면 공유 구조 설계

 

 

✅  데드락 한줄 요약 

형 : "농구공 줄래?"
동생 : "형이 축구공 주면ㅋ"