Skip to content

번 (Deadlock 분석) - 필수 개념 ​

1. 멀티스레드 (Multithreading) ​

정의: 하나의 프로세스 내에서 여러 개의 스레드가 동시에 실행되는 것

프로세스 vs 스레드:

프로세스 (Process):
- 독립적인 프로그램 실행 단위
- 각자 메모리 공간 보유
- 예: 크롬, 유튜브, 카톡 앱

스레드 (Thread):
- 같은 프로세스 내의 실행 단위
- 메모리 공간 공유
- 예: 크롬 내의 여러 탭들이 동시에 작동

우리 테스트:
agent-leak-app 프로세스 내에
├─ Worker-Thread-1
├─ Worker-Thread-2
└─ (다른 스레드들)
이 동시에 실행

2. 자원 (Resource) ​

정의: 여러 스레드가 공유하는 데이터나 객체

우리 테스트의 자원:

1. Shared_Memory_A (공유 메모리)
2. Socket_Pool_B (소켓 풀)

이 둘을 여러 스레드가 동시에 접근하려 함

현실적 예시:

은행의 계좌 잔액 (자원):
- 스레드1: 입금 시도
- 스레드2: 출금 시도
→ 동시에 접근하면 일관성 깨짐
→ 따라서 한 번에 1개 스레드만 접근 가능

3. 락 (Lock / Mutual Exclusion - 상호 배제) ​

정의: 한 번에 1개 스레드만 자원을 사용하도록 제한하는 메커니즘

동작:

Lock 획득:
스레드1: "Shared_Memory_A 사용하겠습니다" (Lock 획득 ✓)
스레드2: "Shared_Memory_A 사용하겠습니다" (Lock 대기... ⏳)

스레드1이 작업 완료:
스레드1: "다 했습니다" (Lock 해제)
스레드2: "이제 사용합니다" (Lock 획득 ✓)

우리 로그에서:

2026-05-27 05:50:08,816 [INFO] LOCK ACQUIRED: [Shared_Memory_A]
→ 이 스레드가 락을 획득함
→ 다른 스레드는 접근 불가

4. 교착상태 (Deadlock) ​

정의: 2개 이상의 스레드가 서로가 가진 자원을 기다리며 무한히 대기하는 상태

우리 테스트의 상황:

시간순서:
T1: 스레드1이 자원A 획득
    스레드2가 자원B 획득

T2: 스레드1이 자원B 필요 → 스레드2가 가지고 있음 → 대기
    스레드2가 자원A 필요 → 스레드1이 가지고 있음 → 대기

T3: 둘 다 자신이 필요한 자원을 못 가지고 있음
    → 영원히 대기 (교착상태)

로그:
2026-05-27 05:50:10,820 [INFO] WAITING for [Socket_Pool_B]... (Status: BLOCKED)
2026-05-27 05:50:10,820 [INFO] WAITING for [Shared_Memory_A]... (Status: BLOCKED)
→ 둘 다 BLOCKED 상태에서 멈춤

현실적 예시:

교과서의 "식사하는 철학자 문제":

철학자 A, B가 앉아있고 포크 2개가 있음
(A 왼쪽에 포크1, 오른쪽에 포크2, B 오른쪽에 포크1... 등)

A: 왼쪽 포크 집음 (포크1 획득)
B: 오른쪽 포크 집음 (포크2 획득)

A: 오른쪽 포크 필요 → B가 가지고 있음 (대기)
B: 왼쪽 포크 필요 → A가 가지고 있음 (대기)

→ 둘 다 영원히 기다림 (밥을 못 먹음)

5. 데드락 4가지 필수 조건 (Deadlock Conditions) ​

데드락이 발생하려면 다음 4가지 조건을 모두 만족해야 함:

조건 1: 상호 배제 (Mutual Exclusion) ​

자원이 배타적으로 사용됨
= 한 번에 1개 스레드만 사용 가능

우리 경우:
Shared_Memory_A는 한 번에 1개 스레드만 접근 가능
Socket_Pool_B도 한 번에 1개 스레드만 접근 가능

✓ 만족

조건 2: 점유 대기 (Hold and Wait) ​

스레드가 자원을 보유하면서 다른 자원 대기
= 가진 것 놓지 않고 필요한 것 기다림

우리 경우:
스레드1: 자원A 보유 → 자원B 대기
스레드2: 자원B 보유 → 자원A 대기

✓ 만족

조건 3: 비선점 (No Preemption) ​

자원을 강제로 빼앗을 수 없음
= 획득한 스레드만 해제 가능

우리 경우:
스레드1이 자원A를 가지면
다른 스레드가 강제로 빼앗을 수 없음
(스레드1이 해제할 때까지 대기)

✓ 만족

조건 4: 순환 대기 (Circular Wait) ​

자원 대기가 순환 구조를 이룸
= A → B → A 형태 (또는 A → B → C → A 등)

우리 경우:
스레드1 (자원A 보유) → 스레드2 (자원B 보유) → 스레드1
                    ↑                              ↓
                    └──────────────────────────────┘

순환 구조!

✓ 만족

결론: 4가지 조건 모두 만족 → 데드락 발생


6. 자원 획득 순서 (Resource Ordering) ​

정의: 여러 자원을 사용할 때 획득하는 순서

문제 상황 (우리 테스트):

스레드1: 자원A → 자원B 순서로 획득
스레드2: 자원B → 자원A 순서로 획득
                 ↑
                다른 순서!

해결책:

모든 스레드가 동일 순서로 획득:

방법1:
스레드1: 자원A → 자원B
스레드2: 자원A → 자원B (동일 순서)

방법2:
스레드1: 자원B → 자원A
스레드2: 자원B → 자원A (동일 순서)

→ 순환 대기 불가능!

7. 블로킹 (Blocking) vs 대기 (Waiting) ​

블로킹 (Blocking):

스레드가 자원을 기다리며 실행을 멈춤

로그에서:
[INFO] WAITING for [Socket_Pool_B]... (Status: BLOCKED)
→ BLOCKED 상태 = 실행하지 않음, 기다리는 중

CPU/메모리 상태:

BLOCKED 상태의 스레드:
- CPU: 0% (실행하지 않음)
- 메모리: 변화 없음 (새로 할당 안 함)
- 로그: 안 나옴 (I/O 수행 안 함)

우리 테스트 결과:

2026-05-27 05:50:10,820 이후:
- CPU: 0%
- 메모리: 정체
- 로그: 없음
→ 모든 스레드가 BLOCKED 상태

출처: Codyssey-B1/B4-2