한정된 대기 (Bounded Waiting)

핵심 인사이트 (3줄 요약)

  1. 본질: 한정된 대기 (Bounded Waiting)는 임계 구역(Critical Section) 보호 알고리즘의 3대 필수 조건 중 마지막으로, 프로세스가 임계 구역에 진입하겠다고 요청한 시점부터 허락될 때까지 다른 프로세스들이 새치기해서 먼저 들어가는 '횟수'에 수학적인 한계(Bound)가 있어야 한다는 원칙이다.
  2. 가치: 아무리 상호 배제(안전)와 진행(활력)이 완벽하더라도, 우선순위가 낮다는 이유로 영원히 락(Lock)을 얻지 못하고 굶어 죽는 **기아 상태(Starvation)**가 시스템에 발생하는 것을 논리적으로 원천 봉쇄하는 '공정성(Fairness)'의 절대 기준이다.
  3. 융합: 현대 운영체제에서는 이를 보장하기 위해 스핀락이나 세마포어의 대기 큐(Wait Queue)를 구현할 때 FIFO(First-In, First-Out) 자료구조를 적용하거나 에이징(Aging) 기법을 융합하여 "언젠가는 반드시 내 차례가 온다"는 강건한 신뢰를 제공한다.

Ⅰ. 개요 및 필요성 (Context & Necessity)

  • 개념: "한정된 대기(Bounded Waiting)"란 단순히 "대기 시간이 짧다"는 뜻이 아니다. 내가 대기줄에 서 있는 동안, 다른 녀석들이 내 앞으로 새치기해서 임계 구역에 들어갈 수 있는 **횟수(Bound)**가 무한대($\infty$)가 아니어야 한다는 수학적 엄밀함을 뜻한다. (예: 최악의 경우라도 내 앞에 3명만 지나가면 내 차례가 무조건 온다).
  • 필요성: 상호 배제(Mutex)로 데이터가 깨지는 것을 막았고, 진행(Progress) 조건으로 데드락을 막았다. 그런데 방이 비었을 때 "누가 들어갈래?"를 결정할 때마다 매번 '우선순위가 가장 높은 VIP'만 들여보낸다면? 평민 프로세스는 시스템이 끝날 때까지 단 한 번도 방에 들어가지 못하고 굶어 죽는다(기아 상태). 시스템의 신뢰도를 보장하려면 모든 참여자에게 "유한한 시간 내의 진입"을 개런티해야 했다.
  • 💡 비유: 놀이공원에서 줄을 섰을 때, VIP 프리패스 손님들이 계속 온다고 해서 일반 손님 줄이 영원히 멈춰있게 놔두지 않고, **"VIP가 3팀 들어가면 무조건 일반 손님 1팀을 들여보낸다"**는 규칙을 세워 일반 손님도 언젠가는 반드시 놀이기구를 타도록 보장하는 것과 같다.
  • 등장 배경: 피터슨 알고리즘이나 베이커리 알고리즘 같은 초창기 소프트웨어 락 설계 시, 특정 프로세스가 무한 루프에 빠지거나 특정 패턴으로 타이밍이 꼬였을 때 한 놈만 영원히 CPU를 못 잡는 취약점이 발견되었다. 이를 막기 위해 데이크스트라가 임계 구역 알고리즘의 세 번째 자격 요건으로 Bounded Waiting을 명문화했다.
  [한정된 대기(Bounded Waiting)의 파괴 vs 준수 시뮬레이션]

  [ ❌ Bounded Waiting 실패 (기아 발생) - LIFO 큐 사용 시 ]
  1. P1 진입 요청 ─▶ 대기 큐: [P1]
  2. P2 진입 요청 ─▶ 대기 큐: [P1, P2] (P2가 더 늦게 왔으나 맨 앞을 차지)
  3. P3 진입 요청 ─▶ 대기 큐: [P1, P2, P3] 
  ▶ 방이 비었을 때: 가장 늦게 온 P3가 먼저 들어감. 계속 새 놈이 오면 P1은 평생 못 들어감!
  ▶ Bound = 무한대 (∞)

  [ ✅ Bounded Waiting 달성 (공정성 보장) - FIFO 큐 사용 시 ]
  1. P1 진입 요청 ─▶ 대기 큐: [P1]
  2. P2 진입 요청 ─▶ 대기 큐: [P1, P2] (P2는 무조건 P1 뒤에 섬)
  3. P3 진입 요청 ─▶ 대기 큐: [P1, P2, P3]
  ▶ 방이 비었을 때: 맨 앞의 P1이 무조건 들어감.
  ▶ Bound = 내 앞의 대기자 수 (유한함)

[다이어그램 해설] 한정된 대기 조건은 "스케줄링의 공정성"을 대변한다. 내가 아무리 찌질한 프로세스라도 큐(Queue)에 들어간 이상, 내 위로 새치기하는 놈의 숫자가 딱 정해져 있어야(Bounded) "언젠가는 끝난다"라는 예측이 가능해진다.

  • 📢 섹션 요약 비유: 은행 창구에서 번호표 기계가 고장 나서 직원 맘대로 손님을 부르는 곳은 한정된 대기가 깨진 곳입니다(기아 발생). 하지만 번호표를 뽑고 대기 인원수가 10명이라고 적혀있으면, 아무리 느려도 내 앞에 10명만 지나가면 내 차례가 온다는 '한정된 대기'가 완벽히 증명됩니다.

Ⅱ. 아키텍처 및 핵심 원리 (Deep Dive)

하드웨어 명령어(TAS)의 약점: 한정된 대기 불만족

원자적 하드웨어 명령어인 TestAndSet (TAS)CompareAndSwap (CAS)를 단독으로 써서 스핀락을 만들면 상호 배제와 진행은 100% 만족하지만, 한정된 대기는 만족하지 못한다.

  // TAS를 이용한 단순 스핀락 (Bounded Waiting ❌)
  while (TestAndSet(&lock) == 1) {
      // 계속 빙빙 돈다 (누가 먼저 락을 잡을지 아무런 보장이 없음)
  }

[이유]: 100개의 스레드가 위 while 문에서 미친 듯이 돌고 있다고 치자. 락이 0으로 풀리는 찰나의 순간, 100명 중 누가 1을 쓰고 들어갈까? 아무런 큐(Queue)도 없기 때문에 순전히 CPU 메모리 버스를 선점한 운 좋은 놈이 들어간다. 만약 지독하게 운이 나쁜 스레드가 있다면, 락이 10만 번 풀리고 닫히는 동안 계속 간발의 차로 타이밍을 놓쳐 영원히 방에 들어가지 못할 수 있다. (기아 상태 발생)

완벽한 3조건을 달성하는 구조: 램포트의 빵집 알고리즘 (Bakery Algorithm)

순수 소프트웨어만으로 "한정된 대기"까지 100% 만족시킨 가장 위대한 알고리즘 중 하나다. 번호표(Ticket) 개념을 도입했다.

  1. 임계 구역에 들어가려는 프로세스는 **번호표(가장 큰 숫자 + 1)**를 뽑는다.
  2. 번호표 숫자가 가장 작은 프로세스가 먼저 들어간다. (FIFO 구조 모방)
  3. 만약 번호표가 우연히 같게 뽑혔다면, 프로세스 ID (PID)가 작은 놈이 먼저 들어간다.

이렇게 하면, 내가 번호표를 10번으로 뽑았다면 그 이후에 온 놈들은 무조건 11번, 12번을 받기 때문에 내 앞으로 새치기할 수 있는 확률은 0%가 된다. (Bound가 명확해짐).

  • 📢 섹션 요약 비유: 빵집에서 번호표 기계(Bakery Algorithm)가 없으면, 빵이 나올 때마다 아줌마들이 벌떼처럼 몰려들어 힘센 사람만 계속 빵을 사 가고 약한 아이는 하루 종일 빵을 못 삽니다(TAS 스핀락의 한계). 번호표를 뽑게 하면, 아이도 "내 앞에 5명만 사 가면 내 차례야"라고 확신(Bounded)할 수 있습니다.

Ⅲ. 융합 비교 및 다각도 분석 (Comparison & Synergy)

운영체제의 락(Lock) 구현: 큐(Queue)의 중요성

현대 운영체제가 뮤텍스(Mutex)나 세마포어(Semaphore)를 만들 때, TestAndSet만 쓰지 않고 **대기 큐 (Wait Queue)**를 결합하는 이유가 바로 한정된 대기 조건을 만족시키기 위함이다.

구현 방식한정된 대기 만족 여부결과
순수 Spinlock (TAS만 사용)❌ 불만족운 나쁜 스레드는 평생 CPU만 갈구고 못 들어감
Mutex (대기 큐 결합)만족못 들어가면 OS가 스레드를 재우고(Sleep), 큐(FIFO)에 줄 세워서 락 풀리면 맨 앞놈을 깨워줌

"Bounded Waiting" vs "Wait-Free"

최신 동시성 프로그래밍에서는 한정된 대기를 넘어선 궁극의 개념들이 등장한다.

  • Bounded Waiting (한정된 대기): "네가 기다리긴 해야 하는데, 평생 기다리진 않을 거야. 언젠간 들어갈게." (락을 쓰는 기존 패러다임)

  • Lock-Free (락 프리): "누군가 한 명은 기다림 없이 무조건 전진해서 끝낼 거야. 나머지는 다시 시도해." (전체적인 시스템의 진행 보장)

  • Wait-Free (웨이트 프리): "줄 서는 것 자체를 없애줄게. 너를 포함한 모든 스레드가 유한한 스텝(명령어) 안에 100% 무조건 작업을 끝낼 거야." (현대 컴퓨터 공학의 끝판왕, 최고 난이도 자료구조)

  • 📢 섹션 요약 비유: '한정된 대기'는 맛집 대기표를 뽑고 1시간 뒤에 입장하는 것입니다. '락 프리'는 식당에 들어가려다 꽉 차면 그냥 딴 데 갔다가 10분 뒤에 다시 와보는 눈치 게임입니다. '웨이트 프리'는 식당에 자리가 무한대라서 문을 열면 0.1초 만에 바로 밥을 먹을 수 있는 마법의 식당입니다.


Ⅳ. 실무 적용 및 기술사적 판단 (Strategy & Decision)

실무 시나리오

  1. 리눅스 Ticket Spinlock과 MCS Spinlock의 도입: 원래 리눅스 커널의 스핀락은 TAS 기반의 눈치 게임이라 한정된 대기(공정성)가 박살나 있었다. 코어가 64개가 되자 재수 없는 코어 하나가 락을 못 잡아 커널 패닉이 터졌다.
    • 아키텍처 혁신: 리눅스 진영은 스핀락에 빵집 알고리즘을 섞은 Ticket Spinlock을 도입하여 "먼저 스핀을 돈 코어가 먼저 락을 잡게(FIFO)" Bounded Waiting을 강제했다. 이후 락을 잡고 도는 행위가 남의 코어 캐시를 더럽히는 걸 막기 위해, 코어별로 자기 로컬 메모리에서만 스핀을 도는 MCS Spinlock / qspinlock으로 완전히 구조를 뒤엎어 공정성과 확장성을 동시에 잡았다.
  2. Java의 ReentrantLock 공정성(Fairness) 옵션 선택: 실무 개발자가 자바에서 명시적인 락을 걸 때 new ReentrantLock(true)new ReentrantLock(false) 중 하나를 선택해야 한다.
    • true (Fair 모드): 한정된 대기(Bounded Waiting)를 100% 보장하는 모드. 먼저 락을 요청한 스레드가 먼저 들어간다(FIFO). 단점은 락을 넘겨줄 때마다 스레드를 깨우고 재우는 문맥 교환이 너무 많이 터져서 서버의 처리량(Throughput)이 절반으로 떨어진다.
    • false (Non-fair 모드, 디폴트): 한정된 대기를 포기하는 모드. 방금 락을 푼 놈이 캐시가 뜨거우니까 바로 다시 락을 채가는 '새치기'를 허용한다. 기아 상태 위험이 있지만, 처리량이 10배 이상 빠르기 때문에 스프링 백엔드에서 99% 이 방식을 쓴다.
  ┌──────────────────────────────────────────────────────────────────┐
  │     락(Lock)의 공정성(Fairness)과 처리량(Throughput) 트레이드오프│
  ├──────────────────────────────────────────────────────────────────┤
  │                                                                  │
  │   [요구사항: 초당 10만 건 결제 처리 락 로직 구현]                │
  │                │                                                 │
  │                ▼ 비즈니스 요건 분석                              │
  │   "1만 번째 고객이 1초 이상 지연되면 소송이 걸리는가?"           │
  │          ├─ [예 (엄격한 지연시간 보장 필수)]                     │
  │          │      │                                                │
  │          │      ▼ 🚨 Fair Lock 강제 적용 (성능 포기)             │
  │          │  모두를 FIFO 큐에 일렬로 세움 (Bounded Waiting).      │
  │          │  ▶ 서버를 10대 더 사서 성능 저하를 돈으로 메꿈.       │
  │          │                                                       │
  │          └─ [아니오 (평균 10만 건 처리량이 더 중요함)]           │
  │                 │                                                │
  │                 ▼ ✅ Non-fair Lock (디폴트) 적용                 │
  │             새치기를 전면 허용하여 스레드 깨우는 시간을 삭제함.  │
  │             ▶ 1명의 고객이 재수 없게 5초 지연될(기아) 수 있으나, │
  │               나머지 99,999명은 0.1초 만에 결제 완료됨.          │
  └──────────────────────────────────────────────────────────────────┘

[다이어그램 해설] 컴퓨터 공학 교과서에서는 "한정된 대기를 반드시 지켜라!"라고 가르치지만, 실무 아키텍트는 안다. "공정함(Fairness)은 가장 비싼 오버헤드다." 공정하게 줄을 세우는 행위 자체가 시스템의 스래싱을 유발하므로, 실무의 기본값은 한정된 대기를 살짝 무시(Non-fair)하여 전체 스루풋을 극대화하는 쪽으로 기울어져 있다.

  • 📢 섹션 요약 비유: 놀이공원 입구에서 표를 검사할 때, 1명씩 정확히 줄을 세워서 검사하면(Fair Lock) 공평하지만 너무 늦게 들어갑니다. 그냥 문을 활짝 열어두고 눈치껏 우르르 밀고 들어가게(Non-fair Lock) 놔두면 얌전한 사람은 좀 늦게 들어가더라도 전체 1만 명이 입장하는 시간은 훨씬 빨라지는 실무적 역설입니다.

Ⅴ. 기대효과 및 결론 (Future & Standard)

기대효과

알고리즘 설계 시 한정된 대기 조건을 완벽히 충족시키면, 수천 개의 스레드가 난립하는 상황에서도 특정 스레드가 무한 루프에 빠지거나 굶어 죽는 '사각지대(Blind Spot)' 없이, "최악의 응답 시간(Worst-case Latency)"을 수학적으로 증명하고 보장하는 철통같은 안전 시스템을 구축할 수 있다.

결론 및 미래 전망

데이크스트라의 3대 요건(상호 배제, 진행, 한정된 대기)은 반세기가 넘도록 운영체제 동기화의 헌법 역할을 해왔다. 하지만 오늘날 100코어가 넘는 클라우드 분산 환경에서는 이 헌법을 완벽히 지키려다 시스템이 멈춰버리는 딜레마(CAP 정리와 유사한 병목)에 부딪히고 있다. 이에 따라 미래의 동시성 패러다임은 한정된 대기를 위한 무거운 큐(Queue)를 버리고, 충돌이 나면 락 없이 우아하게 재시도하는(Retry) **소프트웨어 트랜잭셔널 메모리(STM)**나, 데이터를 읽을 때 락을 거는 대신 아예 최신 스냅샷(Copy-On-Write, RCU)을 던져주고 지나가게 만드는 극단적 락-프리 생태계로 진화하여, 대기(Waiting)라는 단어 자체를 사전에 지워나가고 있다.

  • 📢 섹션 요약 비유: 한정된 대기는 "배급을 공평하게 받기 위해 완벽하게 한 줄 서기"를 강제하는 위대한 질서였습니다. 하지만 인류는 줄 서는 시간을 아끼기 위해 아예 "식량을 복사해서(Copy-On-Write) 전 국민의 집에 배달해 버려 줄 설 일 자체를 없애는" 풍요로운 무한 자원 아키텍처로 넘어가고 있습니다.

📌 관련 개념 맵 (Knowledge Graph)

개념 명칭관계 및 시너지 설명
상호 배제 (Mutual Exclusion)임계 구역 문제 해결의 1원칙. 이기적으로 1명만 들어가게 하는 규칙이라 한정된 대기와 충돌하기 십상이다.
진행 (Progress)방이 비었으면 누구든 빨리 들어가게 하는 2원칙. 한정된 대기(공평함)와 진행(속도)은 영원한 트레이드오프다.
기아 상태 (Starvation)한정된 대기(Bounded Waiting) 조건이 코딩 실수나 Non-fair 락으로 인해 깨졌을 때 발생하는 처참한 결과다.
스핀락 (Spinlock)CPU 하드웨어(TAS)를 써서 빠르지만, 대기 큐(Wait Queue)가 없어 한정된 대기를 본질적으로 위반하는 락이다.
피터슨 알고리즘이 3가지 헌법(상호배제, 진행, 한정된대기)을 소프트웨어 변수 2개(turn, flag)만으로 100% 충족시켜 낸 경이로운 알고리즘이다.

👶 어린이를 위한 3줄 비유 설명

  1. 미끄럼틀을 탈 때, 상호 배제는 "한 번에 1명만 타!"라는 규칙이고, 진행은 "미끄럼틀 비었으면 아무나 빨리 타!"라는 규칙이에요.
  2. 그런데 덩치 큰 형들이 새치기해서 계속 미끄럼틀을 타면, 꼬마 친구는 해 질 때까지 한 번도 못 타는 슬픈 일(기아 상태)이 생겨요.
  3. 그래서 선생님이 **"내 앞에 3명이 탔으면 그다음엔 무조건 내 차례가 온다!"**라고 새치기 횟수에 제한을 두는 게 바로 한정된 대기라는 공평한 규칙이랍니다!