뮤텍스와 세마포어

기술노트
Admin (토론 | 기여)님의 2025년 9월 11일 (목) 16:50 판 (Gemini 벌크 업로더로 자동 업로드)
(차이) ← 이전 판 | 최신판 (차이) | 다음 판 → (차이)

뮤텍스와 세마포어

뮤텍스(Mutex)세마포어(Semaphore)는 병행 프로그래밍 환경에서 공유 자원에 대한 접근을 제어하고 경쟁 상태(Race Condition)를 방지하기 위한 핵심적인 동기화 도구입니다. 둘 다 임계 구역(Critical Section)을 보호하는 데 사용되지만, 동작 방식과 용도에서 중요한 차이를 보입니다.


🔒 뮤텍스 (Mutex)

  • 개념 (Concept) : 'Mutual Exclusion(상호 배제)'의 줄임말. 공유 자원에 대한 접근을 단 하나의 스레드만 허용하도록 제어하는 동기화 도구입니다.
  • 동작 원리

> * 임계 구역에 진입하기 전에 락(Lock)을 획득하고, 임계 구역을 벗어날 때 락을 해제합니다. > * 락을 획득한 스레드만이 임계 구역에 진입할 수 있으며, 다른 스레드는 락이 해제될 때까지 대기합니다.

  • 특징

> * 소유 개념 : 락을 획득한 스레드만이 락을 해제할 수 있습니다. (소유권이 있음) > * 이진 상태 : 락은 '잠김(locked)' 또는 '잠기지 않음(unlocked)'의 두 가지 상태만 가집니다. > * 용도 : 주로 '하나의 공유 자원'에 대한 접근을 제어할 때 사용됩니다. (e.g., 특정 데이터 구조, 파일)

  • 활용 예시 : 화장실에 비유. 화장실 문에 '사용 중' 팻말을 걸고, 들어간 사람만 팻말을 내릴 수 있습니다.

🚦 세마포어 (Semaphore)

  • 개념 (Concept) : 공유 자원에 대한 접근을 제어하는 데 사용되는 변수. '카운터' 역할을 합니다.
  • 동작 원리

> * 세마포어는 정수 값을 가지며, `P()` (또는 `wait()`)와 `V()` (또는 `signal()`) 두 가지 원자적(Atomic) 연산으로만 접근 가능합니다. > * `P()`: 세마포어 값을 1 감소. 값이 0보다 작아지면 해당 프로세스/스레드는 대기합니다. > * `V()`: 세마포어 값을 1 증가. 대기 중인 프로세스/스레드가 있다면 하나를 깨웁니다.

  • 특징

> * 소유 개념 없음 : 락을 획득하지 않은 스레드도 `V()` 연산을 통해 세마포어 값을 증가시킬 수 있습니다. > * 카운터 역할 : 여러 개의 자원에 대한 접근을 제어할 때 사용됩니다. > * 종류 > > * 이진 세마포어 (Binary Semaphore) : 0 또는 1의 값만 가짐. 뮤텍스와 유사하게 상호 배제에 사용될 수 있습니다. > > * 계수 세마포어 (Counting Semaphore) : 0 이상의 정수 값을 가짐. 여러 개의 동일한 자원에 대한 접근을 제어할 때 사용됩니다. (e.g., 프린터 3대)

  • 활용 예시 : 주차장에 비유. 주차 가능 대수(세마포어 값)를 세고, 차가 들어오면 감소, 나가면 증가합니다.

🆚 뮤텍스와 세마포어의 차이점

| 특징 | 뮤텍스 | 세마포어 | |---|---|---| | 목적 | 공유 자원에 대한 '상호 배제' (하나의 스레드만 접근 허용) | 공유 자원에 대한 '접근 제어' (여러 스레드가 동시에 접근할 수 있는 자원의 개수 제어) | | 소유 | 락을 획득한 스레드만 해제 가능 (소유 개념 있음) | 락을 획득하지 않은 스레드도 `V()` 연산 가능 (소유 개념 없음) | | 값의 범위 | 0 또는 1 (잠김/잠기지 않음) | 0 이상의 정수 (이진 세마포어는 0 또는 1) |


💡 개발자 핵심 Point

  • 뮤텍스와 세마포어는 동기화의 가장 기본적인 도구이지만, 잘못 사용하면 데드락(Deadlock)이나 기아 현상(Starvation)과 같은 심각한 문제를 야기할 수 있습니다.
  • 모니터 (Monitor) : 뮤텍스와 세마포어의 복잡성을 줄이고 개발자의 실수를 방지하기 위해 고안된 고수준 동기화 도구입니다. (Java의 `synchronized` 키워드, C#의 `lock` 키워드 등이 모니터 개념을 구현)
  • 실제 개발에서는 직접 뮤텍스나 세마포어를 구현하기보다는, 언어나 프레임워크에서 제공하는 고수준의 동기화 API를 사용하는 것이 일반적입니다. (e.g., `java.util.concurrent.locks.ReentrantLock`, `java.util.concurrent.Semaphore`)