순환 대기 (Circular Wait)
핵심 인사이트 (3줄 요약)
- 본질: 순환 대기 (Circular Wait)는 교착 상태 발생 4조건 중 대미를 장식하는 상태로, 프로세스와 자원들의 대기 관계가 수학 그래프의 완전한 폐쇄 회로(Cycle) 고리 구조(P1→R2→P2→R3→P3→R1→P1)를 형성하여 누구도 진행하지 못하는 구조적 함정이다.
- 가치: 상호 배제나 비선점처럼 시스템 특성상 부정(Prevention)하기 어려운 조건들과 달리, 자원에 선형적 순서(Hierarchy)를 부여하는 규약만으로도 오름차순 접근이 가능해 순환 형성 자체를 절반의 비용으로 완전히 깰 수 있다.
- 융합: 자원 할당 그래프(Resource-Allocation Graph)나 뱅커스(Banker's) 대기 탐색 그래프의 방향성 사이클 검사기, 혹은 DB 엔진의 위상 정렬(Topological Sort) 분석과 융합하여 교착 상태 유무를 가장 시각적, 알고리즘적으로 확정 트리거하는 증거물로 쓰인다.
Ⅰ. 개요 및 필요성
자원 두 개가 있다고 가정하자. 스레드 A가 자원 1을 점유하고 자원 2를 요청한다. 여기까지는 '1자형 라인'이다. 그런데 스레드 B가 동시에 자원 2를 점유하고 자원 1을 요청하는 순간, 두 스레드의 화살표가 **원을 그려 닫히는 고리(Cycle)**를 형성한다. 이 사이클이 바로 **순환 대기(Circular Wait)**다.
직선 대기라면 끝에 있는 스레드가 작업 후 하나씩 풀면 연쇄적으로 해소되겠지만, 닫힌 원 위에서는 누구도 시작점이자 끝점이 될 수 없어 무한 멈춤이 발생한다.
💡 비유: 길게 늘어선 도로 정체 구간. 일직선 정체는 맨 앞차가 빠지면 결국 해소된다. 하지만 차량들이 교차로 네 방향에서 꼬리를 물고 들어가 완벽한 □(정사각형) 링 모양으로 멈추면(Gridlock), 아무리 기다려도 어느 한 차도 먼저 나갈 수 없는 순환 대기에 빠진다.
┌──────────────────────────────────────────────────────────────┐
│ 순환 대기 조건의 무한 루프 형성 구조 │
├──────────────────────────────────────────────────────────────┤
│ │
│ [점유] [요청] │
│ P1 ──────────▶ R1 ──┐ P1 ───▶ R2 (B점유) │
│ ▲ │ │ │
│ │ │ │ │
│ └──────────────────┘ └───────────────────▼ │
│ (사이클 형성: P1 → R2 → P2 → R1 → P1) │
│ │
│ 대기 선형(직선) 모델 (데드락 ❌) │
│ P1 → R1 → P2 → R2 (마지막 P2는 요청할 다른 목표가 없음) │
│ → 언젠가 P2가 R2 완료 시 반납, 그 뒤 선형 연결 풀림. │
│ │
│ 위상 기하학적 의미: 사이클 차수가 1이상 존재. │
└──────────────────────────────────────────────────────────────┘
📢 섹션 요약 비유: 순환 대기는 우물 속에 빠진 세 사람 — 1번이 2번 발목을 잡고, 2번은 3번 발목을 잡고, 3번이 다시 1번 목말을 타고 있는 황당한 고리 구조. 아무도 혼자 손을 못 푸는 영원한 늪입니다.
Ⅱ. 아키텍처 및 핵심 원리
순환 대기 부정 (Prevention: 자원 순서화)
4조건을 찢어버릴 전략들 중에 가장 소프트웨어적으로 현실성 있는 전략이 바로 "순환 대기를 파괴하는 것"이다. 이는 자원에 넘버링 위계(Hierarchy Ordering)를 가해서 강제적인 오름차순(Ascending order) 요청만 허락하면 된다.
┌───────────────────────────────────────────────────────────────┐
│ Lock Hierarchy (락 순서화)를 통한 억제 구조 │
├───────────────────────────────────────────────────────────────┤
│ │
│ 1. 모든 글로벌 자원에 고유 ID (오름차순) 발급 │
│ R1(ID:10), R2(ID:20), R3(ID:30) │
│ │
│ 2. 프로세스의 획득 룰: │
│ "항상 번호표가 낮은 자원부터 먼저 요청해라" │
│ "내가 번호 20을 잡았으면, 절대로 10을 요청할 수 없다" │
│ │
│ 시나리오 우회 도출: │
│ 스레드 A: 10 잡고 20 요청 (✅ 합법) │
│ 스레드 B: 20 잡고 10 요청 (❌ 불법 접근, OS 레벨 코드 거절) │
│ → B는 반드시 10을 먼저 쥐어야 20에 접근 가능하게끔 강제화 │
│ → 원형 형성 가능성 = 0% 완전히 깨짐! │
└───────────────────────────────────────────────────────────────┘
[다이어그램 해설] Lock Order 제약은 다중 락을 디자인할 때의 불문율이다. 무작위 요청 시 터지던 P1(1잡고 2기다림)과 P2(2잡고 1기다림)가 사라지고, 둘 다 (1부터 잡고 2잡음)로 통일되니, 처음부터 1번을 선점한 녀석이 스무스하게 끝내고 반납할 수 있다.
📢 섹션 요약 비유: 은행 서류 창구 순서 — 1번 창구(대출)→2번 창구(승인) 순으로만 가야 하고 역방향 진행은 안 된다고 룰을 정하면 서로 부딪혀 동선이 멈추는 일이 절대 없습니다.
Ⅲ. 융합 비교 및 다각도 분석
순환 대기 부정 모델의 트레이드오프:
| 기법 적용 | 오버헤드 | 설계자 부담 | 실행 병목 |
|---|---|---|---|
| 자원 획득 무질서 개방 | 매우 낮음 | 자유로움 (마음대로 코딩) | 데드락 폭발의 잠재성 |
| 정적 오름차순 부여 | 약간의 리스트 추적비용 | 모든 락 주소를 파악해야 함 | 나중 자원을 미리 잡아야할 때 비효율 유도 |
| 동적 주소 해시 체인 | CPU Hash 연산 추가 | 컴포넌트 객체 참조 자동 정렬 | 자연스러운 데드락 프리(Free) 달성 |
📢 섹션 요약 비유: 순서를 박아두면 편하지만, 가끔은 뒤에 쓸 자원을 앞에 미리 대기번호 뽑아두느라, 정작 필요한 사람의 자리가 막히는 비효율이 조금 생기는 대가가 따릅니다.
Ⅳ. 실무 적용 및 기술사적 판단
실무 시나리오:
- 커널 C코드 개발 가이드라인: Linux 커널에 VFS 등 파일시스템 커밋 시 서로 다른 두 i-node 락을 걸 일이 생긴다면, 룰 매뉴얼에는 "항상 더 낮은 메모리 주소를 가진 i-node 객체를 먼저 잠그고(Lock), 높은 쪽을 잠가라"라고 적혀있다. (이 동적 락 순서화 기법이 순환 대기 박멸의 기본 전술)
- 이체 시스템(Deadlock 자유 동기화): Java로
Account A -> B이체 코드를 짤 때A의 락,B락을 연달아 걸면 교착 상태로 사망한다(B -> A역이체 시). 해결법: System.identityHashCode 로 해시값을 뽑아 값이 더 작은 계좌번호 락부터 획득. 완벽히 사이클을 파괴함.
안티패턴:
- 블랙박스형 서드파티 의존 락: 외부 라이브러리 객체를 동기화할 때, 그 객체 내부에서 자기가 어떤 락을 어떤 내부 순서로 부를지 모르는 상태로 내가 호출을 감싼다(Wrapping Lock). 내부가 내 락 주소와 엇갈리게 락을 시전 시(Reentrant 거부) 보이지 않는 순환 대기 형성. 서브시스템 간 경계를 넘어가는 동기화는 최소화해야 함.
📢 섹션 요약 비유: 계좌 A와 B의 돈 교환은 "언제나 더 작은 잔고 계좌나 번호가 빠른 사람부터 도장 먼저 찍고 가라"고 정해버리면 양쪽 창구가 서로 노려보며 마비되는 일 100% 차단!
Ⅴ. 기대효과 및 결론
| 기준 | 순환 대기 형성(허용) | 순환 대기 원천 차단 |
|---|---|---|
| 프로그래밍 패러다임 | 락 사용 자유 방임주의 | 엄격한 락 순서 획득 의무(Lock Hierarchy) |
| 데드락 안정성 | 탐지 툴/Timeout 없으면 서버 사망 | 수학적으로 데드락 0% 증명 가능 |
| 도입 현실성 | 레거시나 무질서한 DB 구조에 만연 | 가장 프로그래머가 개입할 여지가 뛰어난 방어법 |
교착 상태 4대 근원 중 유일하게 "소프트웨어 설계자의 코드 라인 순서" 만으로 박살 낼 수 있는 가장 취약한 악의 조건이다. 상호 배제나 비선점처럼 OS나 하드웨어 물성에 종속되는 것도 아니고, 점유 대기처럼 극악의 효율 저하를 겪지도 않으니 실무 엔지니어의 데드락 해결 키스톤(Keystone)과 같은 기술이다.
📌 관련 개념 맵
| 개념 | 관계 |
|---|---|
| 자원 할당 그래프 (RAG) | 순환 대기 고리를 시각적 위상으로 증명해내는 유향 그래프 탐지법 |
| 교착 상태 예방 (Deadlock Prevention) | 4조건 중 하나를 치는 전략. '순서화에 의한 순환 대기 부정'이 원탑 모델 |
| 위상 정렬 (Topological Sorting) | 그래프 상에 순환 고리(Cycle)가 존재하는지 수학적으로 스캔하는 탐지 로직의 코어 |
| 락계층 (Lock Hierarchy) | 복수 개의 락을 다룰때 OS 진영에서 강제하는 오름차순 의무 정책 |
👶 어린이를 위한 3줄 비유 설명
- 순환 대기는 강강술래 원 모양 꼬리물기 — 서로 바로 앞사람 등에 달린 이름표를 잡고 놔주지 않으면 결코 원형 춤이 끝나지 않습니다.
- 해결하는 방법은 의외로 쉬워요. "항상 1번부터 차근차근 점차 큰 번호표 이름의 등만 쳐라"고 룰을 주면 아무도 원을 그릴 수 없고 1자형 뱀 꼬리가 돼요.
- 원형이 깨져 1자가 되면 결국 맨 끝사람은 도망갈 수 있고 스르륵 모두 다 풀려나 무한 대기가 끝나는 마법의 방법이랍니다!