백엔드 면접 용어 사전
운영체제semaphore

세마포어

카운터로 동시 진입 허용 수를 제어하는 동기화 장치. 소유권이 없어 다른 주체가 풀 수 있다.

동시에 접근 가능한 개수를 세는 카운터. 값이 0이면 대기, 0보다 크면 통과하며 하나 줄인다.

동작

  • Semaphore(3) — ← 자원 3개

  • acquire() — → 카운터 3 → 2, 통과

  • acquire() — → 2 → 1, 통과

  • acquire() — → 1 → 0, 통과

  • acquire() — → 0 이므로 대기

  • release() — → 0 → 1, 대기하던 하나가 깨어남

주차장 입구의 남은 자리 표시판과 같다. 0이면 나올 때까지 기다린다.

두 종류

쓰임
이진 세마포어0 또는 1상호 배제(뮤텍스와 비슷하지만 소유권 없음)
카운팅 세마포어0 이상동시 접근 수 제한

뮤텍스와 무엇이 다른가 — 소유권과 목적

뮤텍스: "내가 쓰는 동안 아무도 못 들어와"→ 자원 보호
세마포어: "동시에 3명까지"→ 개수 제한 / 신호 전달

세마포어는 소유권이 없어 A가 acquire 하고 B가 release 할 수 있다. 이 성질 때문에 순서 제어(신호 보내기)에 쓸 수 있다.

Semaphore ready = new Semaphore(0);   // 0에서 시작

// 스레드 A (소비자)
ready.acquire();      // 준비될 때까지 대기
process();

// 스레드 B (생산자)
prepare();
ready.release();      // "준비 끝났다"고 신호  ← 잠근 적 없는데 푼다

뮤텍스로는 이런 사용이 불가능하다(자기가 잠근 것만 풀 수 있으므로).

실무에서 가장 흔한 용도 — 동시 실행 수 제한

Semaphore limit = new Semaphore(10);   // 외부 API 동시 호출 10개까지

public Response call() throws InterruptedException {
    limit.acquire();
    try {
        return externalApi.call();
    } finally {
        limit.release();               // finally 필수 — 안 풀면 영구 고갈
    }
}

왜 필요한가 — 외부 시스템이 감당할 수 있는 동시 요청 수는 한계가 있다. 스레드 풀 크기와 별개로 특정 자원에 대한 동시성만 제한하고 싶을 때 쓴다. DB 커넥션 풀도 본질적으로 세마포어다.

tryAcquire(100, MILLISECONDS)빨리 실패시키면 대기 폭증(bulkhead 붕괴)을 막을 수 있다.

고전 문제

  • 생산자-소비자empty(빈 칸 수), full(찬 칸 수) 두 세마포어 + 뮤텍스
  • 식사하는 철학자 — 포크를 세마포어로 표현. 전원이 왼쪽부터 집으면 데드락

함정

release를 빠뜨리면 자원이 영구히 줄어든다. 예외 경로에서 특히 잘 발생한다. 뮤텍스의 synchronized처럼 자동 해제해 주는 문법이 없으므로 try-finally가 필수다.

반대로 release를 더 많이 부르면 카운터가 초기값을 넘어 제한이 무너진다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 운영체제 — 프로세스/스레드·동기화·가상메모리