처리 중 예약까지 합치면 용량이 보존된다.
세 개의 세마포어가 버퍼의 용량과 소유를 분리한다
카운팅 세마포어는 빈 칸과 채운 칸을 예약하고, mutex는 실제 버퍼 변경만 직렬화한다.
put/get 임계 구역에는 한 스레드만 진입한다.
POSIX wait는 감소할 수 있을 때까지 잠든다.
생산자빈 칸 → 데이터
wait(empty)→wait(mutex)→put→post(mutex)→post(full)소비자데이터 → 빈 칸
wait(full)→wait(mutex)→get→post(mutex)→post(empty)순서의 이유: 용량 토큰을 먼저 예약하고 mutex는 짧게 잡는다. 반대로 mutex를 잡은 채 empty/full을 기다리면 상대편도 버퍼에 들어오지 못해 교착될 수 있다.