변수의 기록

(CS 운영체제) 동시성 - 스핀락(spinlock) 뮤텍스(mutex) 세마포(semaphore) 각각 특징과 차이 설명 java 본문

CS지식/운영체제 (Operating System)

(CS 운영체제) 동시성 - 스핀락(spinlock) 뮤텍스(mutex) 세마포(semaphore) 각각 특징과 차이 설명 java

불광동 물주먹 2025. 4. 7. 00:41

✅ [1] Spinlock (스핀락)

🔹 개념

  • 락이 풀릴 때까지 계속 루프 돌며 기다리는 방식
  • test_and_set() 같은 원자적(atomic) 명령어 사용
  • CPU가 제공하는 하드웨어 수준의 atomic 연산을 통해 동기화가 이뤄짐

🔹 핵심 특징

  • 빠르게 락이 풀릴 거라고 예상될 때 유리
  • 락이 오래 걸리면 busy-waiting으로 CPU 낭비 심함
  • 멀티코어 환경에서만 유리

 

사진 출처 - 유튜브 쉬운코드

 

🔹 Java에서?

  • Java는 직접적인 스핀락 지원은 없음
    → AtomicBoolean + 루프로 유사하게 구현 가능 → 또는 LockSupport.park() + CAS 활용으로 구현
  •  

✅ [2] Mutex (뮤텍스)

🔹 개념

  • 상호배제를 위한 소유권 있는 락
  • 락을 얻은 스레드만 해제할 수 있음
  • Java에선 ReentrantLock, synchronized가 대표적인 뮤텍스 구현

🔹 핵심 특징

  • 락 못 잡으면 sleep(waiting) 상태로 들어감 → CPU 절약
  • Priority Inheritance 있음 (우선순위 역전 방지)  ->  (cpu 스케줄링에서 우선순위 낮은 프로그램이 락 가졌을때 cpu 운선 순위를  우선순위가 높은 프로그램과 동일한 우선순위를 부여해줌.)   * 바이너리 세마포와 차이점.
  • 주로 스레드 간 상호 배제 용도

 

사진출처 - 유튜브 쉬운코드

 

🔹 Java에서?

  • synchronized, ReentrantLock 사용
  • ReentrantLock은 tryLock(), 타임아웃, 우선순위 옵션도 있음

✅ [3] Semaphore (세마포어)

🔹 개념

  • 카운터 기반의 동기화 도구
  • 공유 자원 접근 가능 개수만큼 동시 접근 허용
  • signal() / wait() 또는 Java에선 release() / acquire()

🔹 핵심 특징

  • Counting Semaphore: n개까지 동시에 접근 가능
  • Binary Semaphore (이진 세마포어): 0 또는 1 → 뮤텍스처럼 작동하지만 소유권 없음
  • 누가 release할지 알 수 없음 → Priority Inheritance ❌
  • 순서 제어/스케줄링 용도로도 사용 가능 (예: 생산자-소비자 문제)

 

사진 출처 - 유튜브 쉬운코드

 

사진 출처 - 유튜브 쉬운코드

 

🔹 Java에서?

  • java.util.concurrent.Semaphore 사용
  • acquire(), release(), tryAcquire() 등 메서드 제공

 

 

 바이너리 세마포어 (Binary Semaphore)   vs  카운팅 세마포어 (Counting Semaphore) 비교 

 

 1. 바이너리 세마포어 (Binary Semaphore)

🔹 특징

  • 값이 0 또는 1만 가질 수 있음
  • 뮤텍스와 비슷하게 동작 -> 차이점 ( 뮤텍스는 Priority Inheritance 있음 (우선순위 역전 방지)  ->  (cpu 스케줄링에서 우선순위 낮은 프로그램이 락 가졌을때 cpu 운선 순위를  우선순위가 높은 프로그램과 동일한 우선순위를 부여해줌.)   * 바이너리 세마포와 차이점.)
  • 동시에 하나의 스레드만 임계 영역 접근 허용

🔹 용도

  • 상호 배제 (Mutual Exclusion)
  • 락처럼 사용 가능하지만, 소유권 개념이 없음 (즉, 누구나 release 가능)

2. 카운팅 세마포어 (Counting Semaphore)

🔹 특징

  • 값이 0 이상인 정수
    → 자원의 개수(count)를 의미
  • 자원 개수만큼 여러 스레드가 동시에 접근 가능

🔹 용도

  • 공유 자원이 여러 개인 경우 제어 예: 연결 풀, 버퍼, 프린터 3대 등
  • 동작 순서 제어 (생산자-소비자 문제 등)

🔁 차이점 정리표


 

항목 바이너리 세마포어 카운팅 세마포어
값의 범위 0 또는 1 0 이상 (정수)
용도 상호 배제 자원 개수 제어, 순서 제어
유사 도구 뮤텍스와 유사 제한된 연결 풀 같은 구조
동시 접근 허용 수 1명만 여러 명 가능 (count 만큼)
소유권 (release 주체) 없음 (누구나 가능) 없음 (누구나 가능)
Java 클래스 예시 Semaphore(1) (binary처럼 사용) Semaphore(n) (counting으로 사용)

✅ Java에서 예시

// 바이너리 세마포어처럼 사용 Semaphore binary = new Semaphore(1); // 카운팅 세마포어처럼 사용 (예: 최대 5개 자원 허용) Semaphore counting = new Semaphore(5);

 결론 요약

✔️ Binary Semaphore는 "하나만 접근 가능"한 락 느낌
✔️ Counting Semaphore는 "n명까지 접근 가능"한 자원 관리 도구
🔥 뮤텍스와 비슷하지만, 세마포어는 소유 개념이 없다 (누구나 release 가능)


✅ [뮤텍스 vs 세마포어 비교]

 

항목 뮤텍스 (Mutex) 세마포어 (Semaphore)
접근 가능 수 1명 (단일 소유) n명 (카운트 기반)
락 해제 소유자만 가능 누구나 가능
Priority Inheritance ✅ 있음 ❌ 없음
순서 제어 기능 ❌ 없음 ✅ 있음 (순서 조절 가능)
Java 예시 ReentrantLock, synchronized Semaphore 클래스
용도 상호 배제 (Mutual Exclusion) 실행 순서 제어, 동시성 제어 등

✅ test_and_set 이란?

  • CPU가 제공하는 원자적 명령어 (Atomic Instruction)
  • 여러 스레드가 동시에 실행하더라도, 한 순간에 한 스레드만 성공하도록 보장
  • 대부분의 CPU가 LOCK CMPXCHG, XCHG, LL/SC 등 하드웨어 명령 제공

Java에서는?

  • java.util.concurrent.atomic.AtomicBoolean.compareAndSet()
  • Unsafe.compareAndSwapInt() (낮은 수준에서 사용됨)

✅ Java 기준 추가 요약


 

Java  예시 특징
동기화 도구 Java 예시 특징
스핀락 AtomicBoolean + 루프 락이 짧게 유지될 때 유리
뮤텍스 synchronized, ReentrantLock 락 소유 개념, sleep 기반
세마포어 Semaphore 카운트 기반 접근 제어, 순서 제어

✅ 선택 기준 요약


 

상황  권장 도구
단일 스레드만 자원 접근해야 함 뮤텍스 (ReentrantLock)
여러 개의 자원이 있고, 동시에 일부만 접근 허용 세마포어
락이 아주 짧게 걸릴 것 같고, 멀티코어 환경임 스핀락 (Atomic + 루프)
우선순위 역전 방지가 필요함 뮤텍스 사용 (세마포어는 안 됨)

 

 

 

  • 스핀락: 락 걸릴 때까지 계속 CPU 사용하며 대기 (busy wait)
  • 뮤텍스: 락 걸리면 쓰레드를 잠재워 효율적으로 대기
  • 세마포어: 자원 개수를 관리하며 조건 기반 동기화 가능 (카운팅)