ONE QUESTION AT A TIME.

천천히 생각하고, 분명하게.

TODAY’S QUESTION1007 / 1500
동시성난이도 하5분 답변 목표 · 보강본

여러 스레드가 공유 큐에 넣고 꺼내며 큐가 비었을 때 기다립니다. 모니터는 공유 상태·상호 배제·조건 대기를 어떻게 묶어 관리하나요?

잠깐, 답변을 보기 전에
먼저 내 말로 설명해 볼까요?

답변과 점검 포인트 펼치기답변 접기
01

구두 답변

정의를 외우기보다, 원리와 조건을 연결해 설명해 보세요.

모니터는 공유 상태, 그 상태를 조작하는 연산, 상호 배제와 조건 대기를 하나의 추상화로 묶습니다. 작업 큐라면 put과 take가 큐의 불변식을 잠금 안에서 유지하고, 큐가 비어 있으면 소비자가 조건을 기다립니다. 대기하는 동안 잠금을 놓아야 생산자가 큐에 넣을 수 있고, 깨어난 뒤에는 현재 큐 상태를 다시 검사해야 합니다. 상태와 접근 규칙의 소유권을 함께 표현하는 것이 모니터의 역할입니다.

조건은 알림이 아니라 상태입니다

소비자는 ‘누군가 알렸다’가 아니라 ‘지금 큐가 비어 있지 않다’를 조건으로 기다려야 합니다. 여러 소비자가 동시에 깨어나 한 작업을 먼저 가져갈 수 있고, 신호가 다른 이유로 전달되거나 spurious wakeup이 생길 수 있기 때문입니다. Mesa식 모니터에서는 signal 뒤에도 현재 실행 중인 스레드가 계속 진행할 수 있어 깨어난 스레드가 잠금을 다시 얻었을 때 조건이 이미 거짓일 수 있으므로 while로 재검사합니다. Hoare식은 signal한 뒤 대기자가 즉시 실행되는 의미가 달라, 언어·라이브러리 계약을 확인해야 합니다.

모니터가 내부 메서드만 보호할 뿐, 내부 컬렉션의 참조를 그대로 반환해 호출자가 잠금 밖에서 수정하는 것까지 자동으로 막지는 않습니다. callback이나 외부 API를 잠금 안에서 호출하면 재진입·교착·긴 보유 시간이 생길 수 있으므로, 상태를 꺼내 잠금 밖에서 처리하고 필요한 변경을 다시 짧게 잠그는 구조를 우선합니다. 종료 상태도 predicate에 포함해 빈 큐에서 영원히 기다리지 않도록 closed || !queue.empty()처럼 표현하고, 생산자는 종료 후 새 작업을 거절하거나 명시적으로 버립니다.

계약을 실행 순서로 시험합니다

빈 큐·가득 찬 큐·다중 생산자·다중 소비자·동시 종료·callback 재진입을 재현합니다. 검사와 대기, 잠금 해제와 재획득 사이에 스케줄 지연을 삽입해 중복 소비·유실·영구 대기를 찾습니다. 큐 길이·가장 오래된 작업 age·락 보유 시간·소비율과 종료 후 남은 작업을 기록합니다. 모니터라는 이름만 믿지 않고 모든 상태 접근 경로가 같은 잠금·소유권 규칙을 통과하는지 확인하겠습니다.

생산자가 큐를 닫은 뒤 소비자가 빈 큐에서 즉시 종료할지, 남은 작업을 모두 소비한 뒤 종료할지는 모니터의 상태 계약입니다. closed와 empty를 하나로 취급하면 작업 유실이나 영구 대기가 생깁니다. 다중 생산자라면 마지막 생산자만 종료 상태를 바꾸도록 소유권을 정하고, 종료 뒤 새 put을 거절할지 명시합니다. 대기 중인 소비자를 깨운 뒤에도 closed || !queue.empty()를 같은 잠금 아래 다시 검사해야 합니다.

notify 하나는 작업 하나에 소비자 하나를 깨우는 데 적합할 수 있지만 종료처럼 모든 대기자가 상태를 확인해야 하는 경우 broadcast가 필요할 수 있습니다. callback을 잠금 안에서 실행하면 재진입이나 다른 락과의 역순 획득이 생기므로 작업을 꺼낸 뒤 잠금 밖에서 실행하겠습니다. 빈·가득 찬 큐, 동시 종료, callback 재진입에서 중복·유실·영구 대기·락 보유 시간을 확인하겠습니다.

종료 상태는 큐의 empty와 별도입니다. closed=true이고 큐가 비어 있으면 소비자는 종료할 수 있지만, 닫혔어도 남은 작업이 있으면 정책에 따라 먼저 drain해야 합니다. 생산자와 소비자 모두 이 predicate를 같은 잠금 아래 확인하고, 상태 변경 뒤 필요한 대기자에게 알림을 보내야 합니다.

notify 하나를 쓸지 broadcast할지는 상태 전이와 대기자 수에 따라 정합니다. 작업 하나가 들어오면 소비자 하나만 깨우는 편이 효율적일 수 있지만, closed 전환은 모든 대기자가 종료 조건을 다시 확인해야 할 수 있습니다. 잘못된 알림 선택은 thundering herd나 영구 대기를 만들므로 signal 뒤 predicate 재검사와 종료 drain 정책을 함께 검증하겠습니다.

02

득점 포인트

이해가 드러나는 지점을 확인해 보세요.

  • 공유 상태·상호 배제·조건 대기를 하나의 계약으로 설명한다.
  • Mesa식 재검사와 대기 중 잠금 해제를 연결한다.
  • 외부 참조·callback·종료 predicate의 경계를 검증한다.
03

감점 포인트

놓치기 쉬운 조건과 오해를 짚어 보세요.

  • 모니터면 외부에서 반환된 컬렉션도 자동으로 안전하다고 말한다.
  • 기다리는 동안 잠금을 계속 잡아야 한다고 말한다.
  • 모든 언어의 signal 실행 의미가 같다고 단정한다.
04

더 파고들 거리

하나 더 질문하며 이해의 범위를 넓혀 보세요.

득점·감점 포인트는 학습용 자기 점검 기준이며, 특정 회사의 실제 채점표가 아닙니다.

원리부터 공부하고 싶다면

답변을 보충하는 개념·예제·슈도코드를 읽어 보세요.

← 전체 질문 보기