동시성, 교착상태 문제로 고전적으로 나오는 밈? 문제이다.
나도 원래 몰랐는 데 여러군데 돌아다니다 알게 되었다.
문제 설명
5명의 철학자가 원탁에 앉아 있고 각자 앞에 스파게티와 포크가 놓여져 있다.
- 처음에 왼쪽 포크를 집어 든다.
- 그다음 오른쪽 포크를 집어 든다.
- 양손에 두 개의 포크를 모두 쥐었을 때만 스파게티를 먹는다.
- 식사를 마치면 양쪽 포크를 모두 제자리에 내려놓는다.
5명의 철학자 모두 왼쪽 포크는 들고 있을 수 있지만 오른쪽 포크는 없는 상태이기 때문에 어떻게 해야할까?
내 생각
메시지 큐 쓰듯이 그냥 한명씩 순서대로 한입씩 먹으면 되는 거 아닌가..?
아니면 그냥 5명 동시에만 포크를 안들면 되지 않나 하는 생각이다.
교착상태(Deadlock) 발생하는 이유
모든 철학자가 동시에 왼쪽 포크를 집으면, 5개의 포크가 모두 사용 중이 된다. 이제 각 철학자는 오른쪽 포크를 기다리지만, 오른쪽 포크는 옆 철학자가 이미 들고 있다. 아무도 포크를 내려놓지 않으므로 무한 대기 상태에 빠진다.
이는 교착상태의 4가지 조건을 모두 만족한다.
- 상호 배제(Mutual Exclusion): 포크는 한 번에 한 철학자만 사용 가능
- 점유 대기(Hold and Wait): 왼쪽 포크를 든 채 오른쪽 포크를 기다림
- 비선점(No Preemption): 다른 철학자의 포크를 강제로 빼앗을 수 없음
- 순환 대기(Circular Wait): 철학자 0 → 1 → 2 → 3 → 4 → 0 순환 구조로 대기
해결 방법(인터넷에 나와있는 것)
1. 자원 순서화 (Resource Ordering)
교착상태 4가지 조건 중 순환 대기를 깨는 방법이다. 모든 포크에 번호를 매기고, 철학자는 항상 번호가 작은 포크부터 집도록 한다.
마지막 철학자(4번)만 왼쪽(4번 포크)이 아닌 오른쪽(0번 포크)을 먼저 집게 되므로 순환이 깨진다.
철학자 0: fork[0] → fork[1]
철학자 1: fork[1] → fork[2]
철학자 2: fork[2] → fork[3]
철학자 3: fork[3] → fork[4]
철학자 4: fork[0] → fork[4] ← 순서 변경!
2. 세마포어 (Semaphore)
동시에 식사할 수 있는 철학자 수를 최대 4명으로 제한한다. 5개의 포크에 5명이 동시에 접근하지 못하게 하면 최소 한 명은 양쪽 포크를 모두 얻을 수 있다.
semaphore room = 4; // 동시에 4명만 입장 가능
philosopher(i):
wait(room) // 방 입장
wait(fork[i]) // 왼쪽 포크
wait(fork[(i+1)%5]) // 오른쪽 포크
eat()
signal(fork[(i+1)%5])
signal(fork[i])
signal(room) // 방 퇴장
3. Chandy/Misra 해결법
포크를 깨끗한(clean) 상태와 더러운(dirty) 상태로 구분한다.
- 처음에 모든 포크는 더러운 상태로, 번호가 작은 철학자에게 준다
- 포크가 필요하면 이웃에게 요청한다
- 더러운 포크를 가진 철학자는 포크를 깨끗이 닦고 넘겨준다
- 깨끗한 포크를 가진 철학자는 사용할 때까지 넘겨주지 않는다
이 방식은 분산 시스템에서도 동작하며, 기아(starvation) 문제까지 해결한다.
February 20, 2026