📘 Backend/Concurrency

Binary Semaphore와 Mutex의 차이점

신건우 2024. 8. 30. 17:32

Binary Semaphore와 Mutex의 차이점

평소에 개발 시 특정 공유 Resource에 대한 접근은 단일 스레드만 허용해야 하는 기능이 있어서,

ReentrantLock으로 단일 Thread에게 중첩된 Lock을 허용해주는 Mutex 방식으로 개발 했었습니다.


그런데 개발 도중 여러개의 Thread에 권한을 줘야하고 허용 가능한 개수 조절이 필요한 기능이 생겨 Semaphore를 공부 하다가,

Binary Semaphore라는 Mutex와 아주 유사한 동기화 메커니즘을 발견했고 둘 다 단일 스레드만 허용하는 공통점이 있어서

또 어떤 다른 차이가 있는지 궁금해 알아보게 되었습니다.


Binary Semaphore와 Mutex의 공통점

  • Mutex와 Binary Semaphore는 모두 동시성 제어를 위해 사용되며, 하나의 스레드만 자원에 접근하도록 상호 배제 보장
  • 두 방법 모두 공유 자원의 보호를 통해 스레드 간의 Race Condition 방지

주요 차이점

특징 Binary Semaphore Mutex
초기값 0 또는 1 1
소유권 스레드가 아닌 프로세스 또는 스레드 그룹에 의해 관리됨 특정 스레드가 소유하며, 소유한 스레드만 해제 가능
동작 방식 스레드가 acquire()로 자원을 얻고, 다른 스레드도 release()로 자원을 해제할 수 있음 자원을 얻은 스레드만이 release() 호출 가능
사용 목적 자원의 사용을 제한하거나, 스레드 동기화를 위해 사용 주로 상호 배제를 통한 자원 보호에 사용
중첩 잠금 불가능 중첩 잠금(재진입 가능) 가능
커널 수준 지원 커널 수준에서 지원 가능하지만 보편적이지 않음 대부분의 운영체제에서 커널 수준으로 지원

초기값
- Binary Semaphore는 0 또는 1로 초기화할 수 있음
- 이진 세마포어의 값은 공유 자원에 접근할 수 있는 스레드의 수를 나타내며, 초기값이 1이면 자원에 접근 가능한 상태이고, 0이면 접근 불가능한 상태이다
- Mutex는 항상 1로 초기화되며, 이는 자원이 잠겨 있지 않은 상태를 의미함. 자원이 잠기면 Mutex의 값이 0이 되며, 다른 스레드는 해당 자원에 접근할 수 없ㅇㅁ


소유권
- Binary Semaphore는 특정 스레드가 아닌 프로세스나 스레드 그룹에 의해 관리됨
- 따라서 한 스레드가 acquire()한 후 다른 스레드가 release()를 호출할 수 있음
- Mutex는 특정 스레드에 의해 소유되며, 자원을 획득한 스레드만이 자원을 해제(release())할 수 있음
- 따라서 소유한 스레드가 자원을 해제할 때까지 다른 스레드는 대기하게 됨


동작 방식
- Binary Semaphore는 자원을 획득하고 해제하는 책임이 특정 스레드에 한정되지 않기 때문에, 여러 스레드가 acquire()release()를 자유롭게 호출할 수 있음
- Mutex는 자원을 획득한 스레드가 반드시 자원을 해제해야 하는 규칙이 있음. 이는 상호 배제를 엄격하게 유지하도록 설계된 것.


사용 목적
- Binary Semaphore는 스레드 간의 동기화 또는 자원의 사용을 제한하기 위해 사용됨
- 이를 통해 특정 조건이 충족될 때까지 스레드를 대기시키거나, 여러 스레드가 자원에 접근할 수 있는 횟수를 제한할 수 있음
- Mutex는 주로 공유 자원의 동시 접근을 방지하기 위해 사용됨
- 한 번에 하나의 스레드만 자원에 접근할 수 있도록 하여 데이터의 일관성 유지


중첩 잠금
- Binary Semaphore는 중첩 잠금을 지원하지 않음. 즉, 동일한 스레드가 여러 번 acquire()를 호출해도 자원을 잠글 수 없음
- Mutex는 중첩 잠금을 지원하여, 동일한 스레드가 여러 번 자원을 잠글 수 있음
- 이를 "재진입 가능"이라고 하며, 평소에 사용하던 ReentrantLock이 재진입 가능한 Lock 객체임


커널 수준 지원
- Binary Semaphore는 주로 사용자 수준에서 구현되며, 커널 수준에서의 지원이 보편적이지 않음
- Mutex는 대부분의 운영체제에서 커널 수준에서 지원되며, 더 효율적이고 안전하게 구현될 수 있음


Spring에서의 사용 용도 및 차이점

Binary Semaphore
- Spring에서는 Binary Semaphore를 사용하여 스레드 간의 동기화를 수행하거나, 특정 자원에 대한 접근 횟수를 제한할 수 있음
- 예를 들어, 특정 요청의 처리량을 제한하거나, 제한된 자원(예: 데이터베이스 연결)에 대한 접근을 관리할 때 유용함
- 예시: API 요청의 동시 처리량을 제한하고자 할 때, Binary Semaphore를 활용할 수 있음


Mutex
- Spring에서 Mutex는 주로 상호 배제(Mutual Exclusion)를 위해 사용됨
- 이는 특정 자원(예: 파일, 데이터베이스 레코드)에 한 번에 하나의 스레드만 접근하도록 보장하는 데 유용함
- 예시: Singleton 빈의 메서드에서 스레드 간 동기화를 보장해야 할 때, Mutex를 사용할 수 있음
- 예를 들어, synchronized 키워드나 ReentrantLock을 이용하여 Mutex처럼 동작하게 할 수 있음


요약

  • Binary Semaphore는 자원에 대한 접근을 제한하거나 스레드 간의 동기화를 위해 사용되며, 여러 스레드가 acquirerelease를 자유롭게 할 수 있음
  • Mutex는 상호 배제를 보장하기 위해 특정 스레드만이 자원을 잠그고 해제할 수 있도록 하며, 주로 공유 자원의 동시 접근을 방지하기 위해 사용
  • Spring에서 Binary Semaphore는 주로 동시성 제어에 사용되며, Mutex는 상호 배제를 필요로 하는 경우에 사용