Semaphore란
세마포어(Semaphore)는 멀티프로그래밍 환경에서 여러 프로세스나 스레드가 공유 자원에 동시에 접근하는 것을 제어하는 동기화 장치이다.
- 두 개의 원자적 함수로 조작되는 정수형 변수
- 자원 요청 함수:
wait()/P()/acquire() - 자원 반납 함수:
signal()/V()/release()
- 자원 요청 함수:
- Signaling 메커니즘으로 구현
- 락을 걸지 않은 스레드도 signal을 사용해 락을 해제 가능
- 스레드 간 협업에 더 유연
- 세마포어의 카운트를 1로 설정하면 뮤텍스처럼 활용 가능
- Non-Busy-Waiting 방식이다.
Busy-Waiting
Link to original
- 원하는 자원을 얻기 위해 기다리는 것이 아니라 권한을 얻을 때까지 반복적으로 확인하는 것을 의미한다.
- CPU의 자원을 쓸데 없이 낭비하기 때문에 좋지 않은 쓰레드 동기화 방식이다.
종류
- 이진 세마포어: 최대 1개의 프로세스/스레드가 접근 가능한 세마포어
- 카운팅 세마포어: 최대 N개의 프로세스/스레드가 접근 가능한 세마포어
- 강성 세마포어: 대기열을 선입선출(FIFO) 방식으로 관리
- 약성 세마포어: 우선순위를 명시하지 않음, 기아 현상 발생 위험 존재
약성 세마포어를 사용하는 경우
-
관리 오버헤드(Overhead) 최소화: 대기열을 선입선출(FIFO)로 엄격하게 관리하려면 큐(Queue) 상태를 유지하고 스레드의 순서를 추적하는 추가적인 연산 비용이 발생합니다. 약성 세마포어는 이러한 엄격한 큐 관리 비용이 없어 락(Lock) 획득과 해제가 훨씬 빠릅니다.
-
CPU 캐시 효율성 및 컨텍스트 스위칭 감소: 자원이 해제되었을 때 큐의 맨 앞에 있는(가장 오래 대기한) 스레드를 억지로 깨우는 대신, 마침 CPU 스케줄러에 의해 실행 대기 상태에 있거나 캐시에 데이터가 남아있는 스레드가 자원을 즉시 획득하도록 내버려 두면 시스템 전체의 효율이 크게 향상됩니다.
-
작업자 간 구분이 없는 스레드 풀 환경: 웹 애플리케이션의 HTTP 요청 처리처럼 “어떤 스레드가 먼저 클라이언트를 응대하든 상관없이, 남는 스레드가 최대한 빨리 일을 가져가서 전체 처리량만 높이면 되는” 상황에 완벽히 부합합니다.
Java 환경에서 동시성을 제어할 때 사용하는
Semaphore클래스는 기본적으로 약성(Non-fair) 모드로 동작