운영체제나 멀티스레딩 프로그래밍에서 공유 자원에 대한 동기화(Synchronization) 는 매우 중요한 문제다.
여러 개의 스레드나 프로세스가 동시에 자원에 접근할 경우 데이터 충돌, 레이스 컨디션이 발생할 수 있기 때문에, 이를 제어하기 위한 수단으로 세마포어(Semaphore) 와 뮤텍스(Mutex) 가 존재한다.
임계 구역(Critical Section) 이란, 여러 스레드가 동시에 접근해서는 안 되는 공유 자원에 접근하는 코드 영역이다.
이 임계 구역에 동시에 하나의 스레드만 진입하도록 제한해야 한다.
이러한 제한을 구현하는 대표적인 도구가 Semaphore와 Mutex다.
뮤텍스는 "상호 배제"라는 의미 그대로, 동시에 하나의 스레드만 자원에 접근 가능하도록 보장하는 객체다.
pthread_mutex_t lock;
pthread_mutex_init(&lock, NULL);
pthread_mutex_lock(&lock); // 자원 접근
// 임계 구역
pthread_mutex_unlock(&lock); // 자원 반환

세마포어는 뮤텍스보다 더 일반화된 동기화 도구로, 정수 값을 기반으로 자원 개수를 관리한다.
즉, 여러 개의 스레드가 동시에 접근 가능하지만, 정해진 개수만큼만 허용된다.
Counting Semaphore
Binary Semaphore
| 연산 | 설명 |
|---|---|
wait() 또는 P() | 자원 사용 전 호출 (값 감소). 값이 0이면 대기 |
signal() 또는 V() | 자원 사용 후 호출 (값 증가). 대기자 깨움 |
sem_t sem;
sem_init(&sem, 0, 3); // 초기값 3 (최대 3개 동시 접근 가능)
sem_wait(&sem); // 접근 시도
// 임계 구역
sem_post(&sem); // 자원 반납

| 항목 | Mutex | Semaphore |
|---|---|---|
| 목적 | 상호 배제를 통한 자원 보호 | 제한된 개수의 자원 접근 허용 |
| 값 범위 | 0 또는 1 (Binary) | 0 이상 정수 (N개 자원 관리 가능) |
| 소유 개념 | 특정 스레드가 소유 (소유자만 해제 가능) | 소유 개념 없음 (누구나 wait/post 가능) |
| 사용 시점 | 임계 구역 보호 | 리소스 접근 제어 또는 동기화 |
| 예시 사용처 | 변수 보호, 파일 접근 제한 | 쓰레드 간 동기화, 연결 풀 관리 등 |
| 구현 난이도 | 비교적 간단 | 더 유연하지만 사용법에 따라 복잡해질 수 있음 |
동기화 도구는 편리하지만, 잘못 사용하면 데드락(Deadlock) 이 발생할 수 있다.
대표적인 데드락 상황은 다음과 같다:
→ 반드시 락을 획득한 후에는 예외 상황을 대비해 try-finally 또는 unlock을 보장하는 코드를 작성해야 한다.