운영체제 용어 사전
동시성semaphore · 스핀락 · 카운팅 세마포어

세마포어

정해진 개수만큼 동시 접근을 허용하는 동기화 도구. 뮤텍스와 소유권 개념이 다르다.

정해진 개수만큼 동시 접근을 허용하는 동기화 도구.

  • P(wait) — 카운트를 1 줄인다. 0 이면 대기
  • V(signal) — 카운트를 1 늘린다. 대기자가 있으면 깨운다

뮤텍스와의 차이

  • 뮤텍스 — 카운트 1 짜리처럼 보이지만 '소유권' 개념이 있다

    • 잠근 스레드만 풀 수 있다
    • 우선순위 상속 같은 기법을 적용할 수 있다
  • 세마포어 — 소유권이 없다. 누구나 V 를 호출할 수 있다

    • 상호배제뿐 아니라 '신호 전달' 에도 쓴다
    • (한 스레드가 P, 다른 스레드가 V — 생산자·소비자)
  • "화장실 열쇠 1개"(뮤텍스) vs "주차장 자리 N개"(세마포어)

스핀락은 또 다르다

  • 뮤텍스·세마포어 — 대기 시 스레드를 재운다 (컨텍스트 스위치 발생)
  • 스핀락 — 대기 시 CPU 를 돌며 계속 확인한다 (재우지 않는다)

임계 구역이 매우 짧으면 스핀락이 유리하다

  • 전환 비용(수백 ns) > 대기 시간

길면 재앙이다 — CPU 를 태우며 아무 일도 안 한다 단일 코어에서는 특히 나쁘다 (락 가진 스레드가 돌 기회를 뺏는다)

원자 연산

counter++ 는 읽기·증가·쓰기 세 단계라 안전하지 않다

CAS(Compare-And-Swap) 같은 원자 명령을 쓰면 락 없이 안전하다

  • 경쟁이 적으면 락보다 빠르다
  • 경쟁이 심하면 재시도가 폭증해 오히려 느려진다

생산자·소비자에 왜 세마포어가 맞나

sem_t empty, full;   // empty = N, full = 0
sem_init(&empty, 0, BUF_SIZE);
sem_init(&full,  0, 0);

// 생산자
sem_wait(&empty);    // 빈 자리를 하나 소비
lock(); 넣기; unlock();
sem_post(&full);     // 채워진 자리를 하나 알림

// 소비자
sem_wait(&full);
lock(); 꺼내기; unlock();
sem_post(&empty);

생산자가 sem_wait, 소비자가 sem_post 를 호출한다 소유자가 서로 다르므로 뮤텍스로는 표현할 수 없다 — 신호 전달이기 때문이다 상호배제(lock)는 별도로 필요하다. 역할이 다르다

실무에서의 쓰임

  • 동시 처리 개수 제한 — 커넥션 풀 · 외부 API 동시 호출 제한
    • 자바 Semaphore(10) 으로 흔히 구현
  • 속도 제한 — 토큰을 세마포어로 표현

순서를 잘못 쓰면 데드락이 된다

위 코드에서 sem_wait(&empty)lock()의 순서를 뒤집으면, 락을 쥔 채 빈 자리를 기다리게 되어 소비자가 락을 못 잡고 전체가 멈춘다. 대기가 있는 연산은 락 밖에서 — 동시성 코드의 기본 규칙이다.

면접 함정

  • "세마포어는 카운트 1이면 뮤텍스" → 소유권 유무가 다르다.
  • "스핀락이 항상 빠르다" → 임계 구역이 짧을 때만이다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 동시성 — 경쟁 조건·뮤텍스/세마포어·CAS