본문 바로가기
카테고리 없음

동기화 (Mutex & Semaphore) | 컴퓨터과학 기초

by SuldenLion 2026. 7. 20.
반응형
동기화 (Mutex & Semaphore) | 컴퓨터과학 기초
컴퓨터과학 기초 · 02

동기화
Mutex & Semaphore

공유 자원을 안전하게 관리하는 동시성 제어의 핵심
Synchronization OS Concurrency 📖 약 9분

여러 스레드가 동시에 같은 변수를 수정하면 어떻게 될까? 예상치 못한 결과가 나타나는 이 현상을 경쟁 조건(Race Condition)이라 한다. 동기화(Synchronization)는 이 문제를 해결하기 위해 공유 자원에 대한 접근 순서를 제어하는 메커니즘이다.

임계 구역 문제

임계 구역(Critical Section)은 공유 자원에 접근하는 코드 영역이다. 여러 스레드가 동시에 임계 구역에 진입하면 데이터 일관성이 깨진다. 예를 들어 두 스레드가 동시에 counter++를 실행하면 하나의 증가가 무시될 수 있다.

임계 구역 문제를 해결하기 위한 세 가지 조건이 있다.

임계 구역 해결 3대 조건
① 상호 배제 (Mutual Exclusion)
한 번에 하나의 스레드만 임계 구역에 진입할 수 있어야 한다.
② 진행 (Progress)
임계 구역에 진입하려는 스레드가 있다면 반드시 진입이 허용되어야 한다.
③ 한정 대기 (Bounded Waiting)
특정 스레드가 무한히 기다리는 기아(Starvation) 상태가 발생해서는 안 된다.

뮤텍스 (Mutex)

뮤텍스(Mutex, Mutual Exclusion)는 잠금(Lock)/해제(Unlock) 두 가지 상태만을 가진 동기화 객체다. 잠금을 획득한 스레드만이 임계 구역에 진입할 수 있으며, 다른 스레드는 잠금이 해제될 때까지 대기한다.

뮤텍스의 소유권: 뮤텍스는 잠금을 획득한 스레드만이 해제할 수 있다는 소유권(Ownership) 개념이 있다. 이 점이 세마포어와의 핵심적인 차이다.
뮤텍스 동작 순서
스레드 A
🔒 lock() 획득
임계 구역 실행
counter = counter + 1
🔓 unlock() 해제
|
스레드 B
⏳ lock() 대기 중...
⏳ lock() 대기 중...
⏳ lock() 대기 중...
🔒 lock() 획득 (순서대로)
import threading

mutex = threading.Lock()
counter = 0

def increment():
    global counter
    mutex.acquire()  # lock()
    try:
        counter += 1  # 임계 구역
    finally:
        mutex.release()  # unlock()

세마포어 (Semaphore)

세마포어는 정수 카운터를 사용하여 동시에 접근 가능한 자원의 수를 제어한다. P 연산(wait)은 카운터를 감소시키고, V 연산(signal)은 증가시킨다. 카운터가 0이 되면 대기 상태에 진입한다.

세마포어 카운터 예시 (최대 3개 동시 접근)
3
초기 상태
모든 자원 사용 가능
1
2개 사용 중
1개 남음
0
모두 사용 중
다음 스레드 대기

이진 세마포어 vs 카운팅 세마포어

이진 세마포어 (0 or 1)

  • 뮤텍스와 유사하게 동작
  • 단, 소유권 개념 없음
  • 다른 스레드가 해제 가능
  • 신호 전달(Signaling) 용도에 적합

카운팅 세마포어 (N 이상)

  • N개까지 동시 접근 허용
  • DB 커넥션 풀 관리에 적합
  • 생산자-소비자 문제 해결
  • 자원 수를 정확히 관리 가능

뮤텍스 vs 세마포어 비교

구분뮤텍스세마포어
상태잠금 / 해제 (2가지)정수 카운터 (0 ~ N)
소유권있음 (획득한 스레드만 해제)없음 (어느 스레드도 해제 가능)
주 용도단일 자원 상호 배제자원 수 제한, 신호 전달
재귀 잠금구현에 따라 가능 (Recursive Mutex)불가
성능비교적 빠름상대적으로 느림

스핀락 (Spinlock)

스핀락은 잠금이 해제될 때까지 CPU를 점유하면서 반복적으로 확인(Busy Waiting)하는 방식이다. 컨텍스트 스위칭 비용이 없어 잠금 대기 시간이 매우 짧을 때 뮤텍스보다 효율적이다. 그러나 대기 시간이 길면 CPU 자원을 낭비한다.

⚠️ 주의: 스핀락은 단일 코어 시스템에서는 사용하지 않는다. 잠금을 보유한 스레드가 실행될 CPU 자원을 대기 중인 스레드가 모두 소모해버리기 때문이다.

모니터 (Monitor)

모니터는 뮤텍스와 조건 변수(Condition Variable)를 결합한 고수준 동기화 추상화다. Java의 synchronized, Python의 with lock:이 모니터 패턴을 구현한다. 프로그래머가 직접 잠금/해제를 관리할 필요 없이 언어 수준에서 동기화를 보장한다.

정리: 뮤텍스는 "한 번에 하나만" 접근을 보장하는 잠금이고, 세마포어는 "동시에 N개까지" 접근을 제어하는 카운터다. 뮤텍스는 소유권이 있어 자원 보호에, 세마포어는 신호 전달과 자원 제한에 더 적합하다. 현대 고급 언어들은 이들을 추상화한 모니터 패턴을 주로 제공한다.
반응형

댓글