Semaphore란

세마포어(Semaphore)는 멀티프로그래밍 환경에서 여러 프로세스나 스레드가 공유 자원에 동시에 접근하는 것을 제어하는 동기화 장치이다.

  • 두 개의 원자적 함수로 조작되는 정수형 변수
    • 자원 요청 함수: wait() / P() / acquire()
    • 자원 반납 함수: signal() / V() / release()
  • Signaling 메커니즘으로 구현
  • 락을 걸지 않은 스레드도 signal을 사용해 락을 해제 가능
  • 스레드 간 협업에 더 유연
  • 세마포어의 카운트를 1로 설정하면 뮤텍스처럼 활용 가능
  • Non-Busy-Waiting 방식이다.

Busy-Waiting

  • 원하는 자원을 얻기 위해 기다리는 것이 아니라 권한을 얻을 때까지 반복적으로 확인하는 것을 의미한다.
  • CPU의 자원을 쓸데 없이 낭비하기 때문에 좋지 않은 쓰레드 동기화 방식이다.
Link to original

종류

  • 이진 세마포어: 최대 1개의 프로세스/스레드가 접근 가능한 세마포어
  • 카운팅 세마포어: 최대 N개의 프로세스/스레드가 접근 가능한 세마포어
  • 강성 세마포어: 대기열을 선입선출(FIFO) 방식으로 관리
  • 약성 세마포어: 우선순위를 명시하지 않음, 기아 현상 발생 위험 존재

약성 세마포어를 사용하는 경우

  • 관리 오버헤드(Overhead) 최소화: 대기열을 선입선출(FIFO)로 엄격하게 관리하려면 큐(Queue) 상태를 유지하고 스레드의 순서를 추적하는 추가적인 연산 비용이 발생합니다. 약성 세마포어는 이러한 엄격한 큐 관리 비용이 없어 락(Lock) 획득과 해제가 훨씬 빠릅니다.

  • CPU 캐시 효율성 및 컨텍스트 스위칭 감소: 자원이 해제되었을 때 큐의 맨 앞에 있는(가장 오래 대기한) 스레드를 억지로 깨우는 대신, 마침 CPU 스케줄러에 의해 실행 대기 상태에 있거나 캐시에 데이터가 남아있는 스레드가 자원을 즉시 획득하도록 내버려 두면 시스템 전체의 효율이 크게 향상됩니다.

  • 작업자 간 구분이 없는 스레드 풀 환경: 웹 애플리케이션의 HTTP 요청 처리처럼 “어떤 스레드가 먼저 클라이언트를 응대하든 상관없이, 남는 스레드가 최대한 빨리 일을 가져가서 전체 처리량만 높이면 되는” 상황에 완벽히 부합합니다.

Java 환경에서 동시성을 제어할 때 사용하는 Semaphore 클래스는 기본적으로 약성(Non-fair) 모드로 동작

출처 및 참고자료

https://www.tutorialspoint.com/article/mutex-vs-semaphore#:~:text=A%20Mutex%20is%20different%20than,be%20used%20as%20a%20semaphore