둠치킨
코딩하는 둠치킨
둠치킨

블로그 메뉴

  • 홈
  • 분류 전체보기 (218) N
    • BOJ (171) N
      • 스택 (14)
      • 큐 (5)
      • 덱 (4)
      • 그래프 (30)
      • 배열 (8)
      • 재귀 (12)
      • 브루트 포스 (2)
      • 그리디 알고리즘 (7)
      • 다이내믹 프로그래밍 (13)
      • 백트래킹 (24)
      • 기하학 (4)
      • 트리 (4)
      • 구현 (14)
      • 수학 (3)
      • 맵 (1)
      • 다익스트라 (2)
      • 누적합 (5) N
    • 자료구조 (14)
      • 스택 (3)
      • 큐 (5)
      • 덱 (2)
      • 그래프 (1)
      • 트리 (1)
      • 힙 (1)
      • 정렬 (1)
    • C++ (11)
      • 모두의코드 (2)
      • Effective C++ (3)
      • C++ STL (6)
    • 컴파일러 (1)
    • OS (17)
    • 컴퓨터 구조 (2)
    • Unreal Engine 5 (2)

공지사항

전체 방문자
오늘
어제

인기 글

최근 글

태그

  • BFS
  • boj
  • Bruteforce
  • C
  • C++
  • C++ STL
  • Cache Memory
  • deadlock
  • DFS
  • Effective C++
  • java
  • Mutex
  • next_permutation
  • os
  • Process
  • rotate
  • semaphore
  • spin lock
  • STL
  • STL C++
hELLO · Designed By 정상우.
둠치킨

코딩하는 둠치킨

OS

세마포어(Semaphore)

2025. 6. 24. 20:58

세마포어

멀티스레드나 멀티프로세스 환경에서는 여러 실행 흐름이 동시에 하나의 공유 자원에 접근할 수 있기 때문에, 예상치 못한 충돌이나 오류가 발생할 수 있다.
이를 방지하기 위해 등장한 동기화 도구 중 가장 기본적이면서 강력한 것이 바로 세마포어(Semaphore)이다.

세마포어는 크게 카운팅 세마포어와 이진 세마포어로 나뉘며, 이 글에서는 두 종류를 각각 개념부터 동작 방식, 예외 사항까지 정리한다.


1. 범용 세마포어 (카운팅 세마포어)

개념

카운팅 세마포어는 정수 값을 가지는 동기화 객체로, 여러 개의 동일한 공유 자원을 보호할 때 사용된다.
세마포어의 값은 현재 사용 가능한 자원의 수를 의미하며, 프로세스나 스레드가 자원을 사용할 때는 값을 감소시키고, 반납할 때는 값을 증가시킨다.

연산

  • 초기화: 자원의 개수만큼 0 이상의 값으로 초기화
    예를 들어 3개의 프린터를 보호하려면 세마포어를 3으로 초기화한다
  • wait() 연산 (P 연산)
    세마포어 값을 1 감소
    감소 후 값이 음수이면, 해당 프로세스는 블록되어 대기열에 들어간다
  • signal() 연산 (V 연산)
    세마포어 값을 1 증가
    만약 대기 중인 프로세스가 있다면 하나를 깨운다

값의 의미

  • 양수: 자원이 남아 있어 바로 사용 가능
  • 0: 자원이 모두 사용 중이며, 새로운 접근은 대기해야 함
  • 음수: 절댓값만큼의 프로세스가 대기 중

큐 정책

  • 강성 세마포어: 가장 오래 대기한 프로세스를 먼저 깨운다 (FIFO)
  • 약성 세마포어: 스케줄러가 자유롭게 선택

특징

  • 자원이 0이 아닐 경우 블록되지 않고 수행된다
  • signal은 블록된 프로세스가 없더라도 항상 값을 증가시킨다
  • wait과 signal은 반드시 원자적이어야 하며, 수행 중 끼어들 수 없다
  • 카운팅 세마포어는 동시에 여러 프로세스가 접근 가능하므로, 다중 자원 보호에 적합하다

2. 이진 세마포어 (Binary Semaphore)

개념

이진 세마포어는 0 또는 1의 값만을 가지는 세마포어로, 오직 하나의 자원만을 보호할 때 사용된다.
기본적인 구조와 동작 방식은 카운팅 세마포어와 같지만, 값이 1 이상 되지 않도록 제한된다.

연산

  • 초기화: 1로 초기화하여 하나의 자원이 존재함을 표시
  • wait()
    세마포어 값이 1이면 0으로 만들고 진입
    세마포어 값이 0이면 해당 프로세스는 블록됨
  • signal()
    대기 중인 프로세스가 있으면 그 프로세스를 깨움
    없으면 세마포어 값을 1로 설정

특징

  • 하나의 자원을 보호하기 위한 동기화 기법
  • 뮤텍스와 매우 유사한 구조를 가지지만, 소유 개념이 없다는 차이가 있다
  • 카운팅 세마포어보다 구현이 간단하고 가벼운 대신, 동시 접근이 필요한 경우에는 사용할 수 없다

세마포어 요약 비교

항목 카운팅 세마포어 이진 세마포어
값의 범위 0 이상 0 또는 1
자원 수 여러 개 1개
사용 목적 다중 자원 보호 단일 자원 보호
구현 복잡도 다소 복잡 간단
사용 예시 프린터 여러 대, 연결 제한 임계 영역 보호, 플래그 제어

세마포어와 뮤텍스의 차이

항목 세마포어 뮤텍스
자원 수 여러 개 자원 (카운팅 가능) 하나의 자원 (단일 보호)
소유 개념 없음 (누구나 wait, signal 가능) 있음 (lock한 스레드만 unlock 가능)
사용 범위 프로세스 간, 스레드 간 모두 가능 주로 스레드 간
연산 이름 wait(), signal() lock(), unlock()
용도 접근 횟수 제어, 흐름 제어 상호 배제 (Mutual Exclusion)
구현 복잡도 비교적 복잡 상대적으로 간단
 

이진 세마포어와 뮤텍스의 차이

이진 세마포어와 뮤텍스는 모두 한 번에 하나의 스레드만 공유 자원에 접근하게 만드는 동기화 도구라는 점에서 기능적으로 유사해 보인다.
하지만 두 도구 사이에는 중요한 차이가 있다.

  • 이진 세마포어는 소유 개념이 없다.
    자원을 점유한 스레드가 아니더라도 누구나 signal()을 호출해 세마포어 값을 1로 만들어 다른 스레드를 깨울 수 있다.
    이로 인해 보다 범용적이며, 단순한 순서 제어나 동기화에도 사용된다.
  • 뮤텍스는 소유 개념이 있다.
    lock()을 호출해 뮤텍스를 획득한 해당 스레드만이 unlock()을 호출할 수 있다.
    이로 인해 명확한 소유권 기반의 상호 배제가 가능하며, 임계영역 보호에 특화된 도구이다.

결론적으로,
이진 세마포어는 더 범용적인 동기화 용도에 적합하며,
뮤텍스는 소유 개념을 통해 더 엄격한 상호 배제를 보장한다.

저작자표시 (새창열림)

'OS' 카테고리의 다른 글

프로그램은 어떻게 실행되는가  (0) 2025.06.24
스핀락(Spin Lock)  (3) 2025.06.24
뮤텍스(Mutex)  (0) 2025.06.24
멀티쓰레드 환경에서 생길 수 있는 문제들  (0) 2025.06.24
다양한 OS 스케줄링 기법  (0) 2025.06.24
    'OS' 카테고리의 다른 글
    • 프로그램은 어떻게 실행되는가
    • 스핀락(Spin Lock)
    • 뮤텍스(Mutex)
    • 멀티쓰레드 환경에서 생길 수 있는 문제들
    둠치킨
    둠치킨
    코딩 공부를 위한 코딩 블로그 기록 일기

    티스토리툴바