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


819

이진 세마포어와 뮤텍스 사이에 차이점이 있습니까? 아니면 본질적으로 동일합니까?


11
그것들은 의미 상 동일하지만 실제로 이상한 차이 (특히 Windows에서)를 알 수 있습니다.
Michael Foukarakis

5
@Michael Foukarakis : 이상한 차이점은 무엇입니까?
Philipp

2
나는 이상한 표현이 올바른 표현이 아니라고 생각합니다. 뮤텍스는 소유권과 때로는 재진입도 지원합니다. 이것은 Windows의 경우입니다. 또한 Windows의 세마포어는 Event 객체 위에 구현되지만 이것이 실제로 어떤 영향을 미치는지 확신하지 못합니다.
Michael Foukarakis


2
@philipxy 'm'대신 'rn'을 멋지게 숨겼습니다.
Mooncrater

답변:


691

그들은이다 NOT 같은 일. 그들은 다른 목적으로 사용됩니다!
두 유형의 세마포어가 전체 / 빈 상태이며 동일한 API를 사용하지만 사용법은 매우 다릅니다.

상호 배제 세마포어
상호 배제 세마포어는 공유 리소스 (데이터 구조, 파일 등)를 보호하는 데 사용됩니다.

Mutex 세마포어는 그것을 수행하는 작업에 의해 "소유"됩니다. 작업 B가 작업 A가 현재 보유하고있는 뮤텍스를 표시하려고하면 작업 B의 호출이 오류를 반환하고 실패합니다.

뮤텍스는 항상 다음 순서를 사용합니다.

  -SemTake
  -중요 섹션
  -SemGive

다음은 간단한 예입니다.

  스레드 A 스레드 B
   뮤텍스를
     액세스 데이터
     ... Mutex 사용 <== 차단
     ...
   Mutex 액세스 데이터 제공 <== 차단 해제
                                  ...
                                뮤텍스 제공

이진 세마포
이진 세마포는 완전히 다른 질문을 다룹니다.

  • 작업 B는 무언가가 발생하기를 기다리는 중입니다 (예 : 센서가 트립 됨).
  • 센서 트립 및 인터럽트 서비스 루틴이 실행됩니다. 여행을 작업에 알려야합니다.
  • 작업 B가 실행되고 센서 트립에 적절한 조치를 취해야합니다. 그런 다음 대기로 돌아갑니다.

   Task A                      Task B
   ...                         Take BinSemaphore   <== wait for something
   Do Something Noteworthy
   Give BinSemaphore           do something    <== unblocks

이진 세마포어를 사용하면 B가 세마포어를 사용하고 A를 지정하는 것이 좋습니다.
이진 세마포어는 리소스 액세스를 보호하지 않습니다. 세마포어를주고받는 행위는 근본적으로 분리되어 있습니다.
일반적으로 동일한 작업에 대해 동일한 이진 세마포어를주고받는 것이 거의 의미가 없습니다.


12
뮤텍스가 이진 세마포어보다 낫지 않습니까? 누군가가 실제로 보유하지 않은 자물쇠를 놓으면 말이되지 않습니다.
Pacerier

111
그들은 다른 목적을 가지고 있습니다. Mutex는 리소스에 독점적으로 액세스하기위한 것입니다. 이진 세마포어를 동기화에 사용해야합니다 (예 : "Hey Someone! This 발생!"). 이진 "주는 사람"은 단순히 "테이커"에게 그들이 기다리고 있었던 것을 알립니다.
Benoit

5
@Pacerier 목적을 혼동하고 있습니다. 뮤텍스는 중요한 영역을 보호하기위한 것입니다. 이진 세마포어를 사용하는 것은 이치에 맞지 않습니다. 각각의 목적을 설명하기 위해 답변을 업데이트하겠습니다.
Benoit

4
@Benoit 그래서 Mutex는 원 자성 및 이진 세마포어에 사용된다고 할 수 있습니까? 태스크 B는 태스크 A가 데이터 스트럭처에 대한 오퍼레이션 순서를 본질적으로 보장하는 잠금 해제를 신호하기를 기다리고 있기 때문에 주문 관점에서?
abhi

1
@abhi 뮤텍스를 살펴 보는 좋은 방법입니다. 그러나 OS에 따라 이진 세마포어를 기다리는 수신자가 둘 이상있을 수 있습니다. 이 경우 클라이언트 중 하나만 이진 sem을 가져옵니다. 다른 사람들은 다음을 기다릴 것입니다. 수령 순서가 알려 지거나 보장됩니까? OS에 따라 다릅니다.
Benoit

446
  • 뮤텍스는 만 해제 할 수 를 획득 한 스레드 .
  • 바이너리 세마포어가 신호를받을 수 있는 스레드 (또는 프로세스).

따라서 세마포어는 생산자 소비자와 같은 일부 동기화 문제에 더 적합합니다.

Windows에서 이진 세마포어는 뮤텍스보다 이벤트 객체와 유사합니다.


34
Mutex can be released only by thread that had acquired it-방금 간단한 pthread_mutex 기반 프로그램을 사용해 보았습니다. 스레드는 메인 스레드에 뮤텍스를 잠금 해제 할 수 있습니다
데이지

15
@ warl0ck pthread_mutex_lock linux.die.net/man/3/pthread_mutex_lock 매뉴얼 페이지에 따라 : "뮤텍스 유형이 PTHREAD_MUTEX_ERRORCHECK이면 오류 검사가 제공됩니다 .... 잠금 상태가 아니거나 잠금 해제 된 뮤텍스가 있으면 오류가 반환됩니다. "
amit jan

47
@ warl0ck 참조하시기 바랍니다 stackoverflow.com/a/5492499/385064 'Pthreads에는 빠른 뮤텍스, 재귀 뮤텍스 및 오류 확인 뮤텍스의 세 가지 종류의 뮤텍스가 있습니다. 성능상의 이유로이 오류를 확인하지 않는 빠른 뮤텍스를 사용했습니다. Linux에서 오류 검사 뮤텍스를 사용하면 예상 한 결과를 얻을 수 있습니다. '
FrostNovaZzz

1
우리 코드에서는 동기화 목적으로 뮤텍스를 사용했습니다. 뮤텍스를 잠그는 스레드는 다시 뮤텍스를 잠그려고 시도했습니다. 우리는 posix 표준 만 사용하고 있기 때문에 뮤텍스와 이진 세마포어 사이의 주요 차이점은 모호해 보입니다.
achoora

1
@achoora 동기화를 위해 세마포어를 특수화하는 것이 잘못되었음을 동의합니다. 실제로 모든 뮤텍스, 이진 세마포어, 배리어, 파이프 라인은 동기화를위한 다른 패턴입니다. 디자인 관점에서 뮤텍스는 상태에 의해 선택된 알고리즘이 상태를 변경할 수있는 상태 패턴과 더 비슷합니다. 이진-세마포어는 외부 알고리즘이 상태를 변경하고 결과적으로 알고리즘 / 전략이 실행되도록 선택한 전략 패턴과 비슷합니다.
shuva

442

화장실 예제 는 즐거운 유추입니다.

뮤텍스 :

화장실의 열쇠입니다. 한 번에 한 사람이 화장실을 차지하는 열쇠를 가질 수 있습니다. 완료되면, 사람은 대기열에있는 다음 사람에게 키를 제공합니다.

공식적으로 : "뮤텍스는 일반적으로 하나 이상의 스레드가 동시에 실행할 수없는 재진입 코드 섹션에 대한 액세스를 직렬화하는 데 사용됩니다. 뮤텍스 객체는 하나의 스레드를 제어 된 섹션으로 만 허용하여 다른 스레드가 액세스하려고 시도합니다. 첫 번째 스레드가 해당 섹션에서 나올 때까지 해당 섹션을 기다리십시오. " 참고 : Symbian 개발자 라이브러리

(뮤텍스는 실제로 값이 1 인 세마포입니다.)

신호기:

동일한 무료 화장실 키의 수입니다. 예를 들어, 자물쇠와 열쇠가 같은 화장실이 4 개 있다고 가정합니다. 세마포어 수 (키 수)는 처음에 4로 설정되고 (4 개의 화장실은 모두 무료) 사람들이 들어 오면 카운트 값이 감소합니다. 모든 화장실이 가득 찬 경우, 즉 남아있는 빈 키가 없으면 세마포어 카운트는 0입니다. 이제 eq. 한 사람이 화장실을 떠나면 세마포어가 1 (무료 키)로 증가하고 대기열의 다음 사람에게 제공됩니다.

공식적으로 : "세마포어는 공유 리소스의 동시 사용자 수를 최대 수로 제한합니다. 스레드는 리소스에 대한 액세스를 요청 (세마포 감소)하고 리소스 사용이 완료되었음을 알리는 신호를 줄 수 있습니다 (세마포 증가). " 참고 : Symbian 개발자 라이브러리


234
...하지만 이것은 뮤텍스 대 세마포 계산에 관한 것입니다. 이진에 대한 질문이있었습니다.
로마 Nikitchenko

24
david가 말한 내용은 정확하지만 질문에 대한 답변이 아닙니다. Mladen Jankovic의 답변은 "이진-세마포어"와 "뮤텍스"를 구별하기위한 질문에 대한 답변입니다.
Ajeet Ganga

13
불행히도,이 잘못된 답변은
@Benoit

6
이 답변은 오도의 소지가 있으며 이진 세마포어와 비교했을뿐입니다.
Hemanth

3
이것은 또한 계산 세마포어를 사용하여 공유 리소스를 보호하는 데 문제가 있음을 보여줍니다. 키가 실제로 동일하고 키를 사용하여 화장실이 잠금 해제되어 있고 큐비클 사용을 분배하는 다른 메커니즘이없는 경우 : (1) 첫 번째 사용자는 첫 번째 칸막이를 잠금 해제하고 들어가서 사용하기 시작합니다. (2) 다음 사용자가 첫 번째 칸막이를 잠금 해제하고 들어 와서 사용하기 시작합니다.
Technophile

151

주제에 대한 좋은 기사 :

2 부에서 :

뮤텍스는 하나의 중요한 차이점 인 소유권 원칙이라는 점에서 이진 세마포어의 원리와 유사합니다. 소유권은 작업이 뮤텍스를 잠 그거나 (취득 할 때) 잠금 해제 (릴리스) 할 수있는 간단한 개념입니다. 작업이 뮤텍스의 잠금을 해제하려고 시도하면 잠기지 않았으므로 (따라서 소유하지 않음) 오류 조건이 발생하며 가장 중요한 것은 뮤텍스가 잠금 해제되지 않은 것입니다. 상호 배제 객체에 소유권이없는 경우 객체와 상관없이 뮤텍스가 아닙니다.


링크 주셔서 감사합니다, 설명이 우수합니다. feabhas.com/blog/2009/09/… 링크가 변경되었습니다 (<이전 및 다음>을 사용하여 다른 두 기사로 이동하십시오.
Aaron H.

@Aaron 링크를 수정했습니다
Maygarden 판사

참고-소유권이 없으면 운영 체제가 우선 순위 역전으로 작동하지 않습니다. 이러한 이유로 나는 일반적으로 생산자 / 소비자 아키텍처의 세마포어와 달리 조건 변수를 사용합니다.
kgriffs

1
적에게 훌륭한 기사 링크 +1. "what-it-is"와 "what-it-does" computing.llnl.gov/tutorials/pthreads 를 사용 하여 세마포어와 뮤텍스를 설명하는 가장 좋은 기사 뮤텍스 / 조건부 및 기타 구조는 세마포어 / 배리어 / 리더-라이터와 같이 맨 위에 지어졌지만 구조에 직면 한 문제에 대해서는 명시적이고 간결하지 않습니다. 요컨대 그것은 참조입니다. :)
Ajeet Ganga

다른 답변보다 쉽게 ​​이해할 수 있습니다.
BinaryTreeee

101

위의 답변 중 어느 것도 혼란을 해결하지 못하므로 여기 내 혼란을 해결 한 것이 있습니다.

엄밀히 말하면, 뮤텍스는 리소스에 대한 액세스를 동기화 하는 데 사용되는 잠금 메커니즘 입니다. 하나의 작업 (OS 추상화에 기반한 스레드 또는 프로세스 일 수 있음) 만 뮤텍스를 획득 할 수 있습니다. 이는 mutex와 관련된 소유권이 있으며 소유자 만 잠금 (mutex)을 해제 할 수 있음을 의미합니다.

세마포어는 신호 전달 메커니즘입니다 (“완료되었습니다. 계속 진행할 수 있습니다”). 예를 들어, 모바일에서 노래를 듣고 (한 작업으로 가정) 친구가 전화를 걸면 인터럽트 서비스 루틴 (ISR)이 호출 처리 작업을 깨우도록 신호를주는 인터럽트가 트리거됩니다. .

출처 : http://www.geeksforgeeks.org/mutex-vs-semaphore/


42

그들의 동기화 의미는 매우 다릅니다 :

  • 뮤텍스는 주어진 리소스에 대한 액세스의 직렬화를 허용합니다. 즉, 여러 스레드가 한 번에 하나씩 잠금을 대기하며 앞에서 말했듯이 스레드 잠금이 완료 될 때까지 잠금을 소유 합니다. 이 특정 스레드 잠금을 해제 할 수 있습니다.
  • 이진 세마포어 값이 0과 1로 카운터입니다 : 때까지 작업이 그것에 차단 어떤 작업이 sem_post 않습니다. 세마포어는 리소스가 사용 가능함을 알리고, 사용 가능하다고 신호 될 때까지 대기하는 메커니즘을 제공합니다.

따라서 뮤텍스를 작업에서 작업으로 전달 된 토큰으로, 세마포어를 트래픽 빨간색 표시등으로 볼 수 있습니다 (누군가 진행할 수 있음을 알리는 신호 ).


23

이론적으로는 의미 적으로 다르지 않습니다. 세마포어를 사용하거나 그 반대로 뮤텍스를 구현할 수 있습니다 ( 예는 여기 참조 ). 실제로는 구현 방식이 다르며 약간 다른 서비스를 제공합니다.

실질적인 차이 (그들을 둘러싼 시스템 서비스의 관점에서)는 뮤텍스의 구현이보다 가벼운 동기화 메커니즘이라는 것을 목표로합니다. oracle-speak에서 뮤텍스는 래치로 , 세마포어는 대기 로 알려져 있습니다 .

가장 낮은 수준에서는 원자 테스트 및 설정 메커니즘을 사용합니다. 이것은 메모리 위치의 현재 값을 읽고, 일종의 조건부 조건을 계산하고, 중단 될 수없는 단일 명령으로 해당 위치의 값을 씁니다 . 즉, 뮤텍스를 획득하고 다른 사람이 뮤텍스를 가지고 있는지 확인하기 위해 테스트 할 수 있습니다.

일반적인 뮤텍스 구현에는 테스트 및 설정 명령어를 실행하고 다른 어떤 것이 뮤텍스를 설정했는지 평가하는 프로세스 또는 스레드가 있습니다. 여기서 중요한 점은 스케줄러 와 상호 작용이 없기 때문에 누가 잠금을 설정했는지 알 수 없습니다. 그런 다음 시간 조각을 포기하고 작업이 다시 예약 될 때 다시 시도하거나 spin-lock을 실행합니다 . 스핀 잠금은 다음과 같은 알고리즘입니다.

Count down from 5000:
     i. Execute the test-and-set instruction
    ii. If the mutex is clear, we have acquired it in the previous instruction 
        so we can exit the loop
   iii. When we get to zero, give up our time slice.

보호 된 코드 ( critical section ) 실행을 마치면 뮤텍스 값을 0 또는 'clear'라는 의미로 설정하면됩니다. 여러 작업이 뮤텍스를 획득하려고 시도하는 경우 뮤텍스가 릴리스 된 후 예약 된 다음 작업은 리소스에 액세스 할 수 있습니다. 일반적으로 뮤텍스를 사용하여 독점 액세스가 매우 짧은 시간 동안 만 필요한 경우 일반적으로 공유 데이터 구조를 업데이트하는 동기화 된 리소스를 제어합니다.

세마포어는 뮤텍스 라이브러리보다 약간 더 깊이있는 스케줄러와 상호 작용하는 카운트 및 일부 시스템 호출 래퍼가있는 동기화 된 데이터 구조 (일반적으로 뮤텍스 사용)입니다. 세마포어는 증가하고 감소하여 다른 준비가 될 때까지 작업 을 차단 하는 데 사용됩니다 . 이에 대한 간단한 예는 생산자 / 소비자 문제 를 참조하십시오 . 세마포어는 어떤 값으로 초기화됩니다-이진 세마포어는 세마포어가 1로 초기화되는 특별한 경우입니다. 세마포어에 게시하면 대기 프로세스를 깨우는 효과가 있습니다.

기본 세마포어 알고리즘은 다음과 같습니다.

(somewhere in the program startup)
Initialise the semaphore to its start-up value.

Acquiring a semaphore
   i. (synchronised) Attempt to decrement the semaphore value
  ii. If the value would be less than zero, put the task on the tail of the list of tasks waiting on the semaphore and give up the time slice.

Posting a semaphore
   i. (synchronised) Increment the semaphore value
  ii. If the value is greater or equal to the amount requested in the post at the front of the queue, take that task off the queue and make it runnable.  
 iii. Repeat (ii) for all tasks until the posted value is exhausted or there are no more tasks waiting.

이진 세마포어의 경우 두 데이터 간의 주요 실제 차이점은 실제 데이터 구조를 둘러싼 시스템 서비스의 특성입니다.

편집 : 에반이 올바르게 지적했듯이 스핀 락은 단일 프로세서 시스템을 느리게합니다. 단일 프로세서에서는 다른 작업이 실행되는 동안 뮤텍스를 유지하는 프로세스가이를 재설정하지 않기 때문에 다중 프로세서 상자에서만 스핀 락을 사용합니다. 스핀 록은 다중 프로세서 아키텍처에서만 유용합니다.


1
나는 뮤텍스가 스핀 락으로 구현되는 것이 일반적인 관행이라고 생각하지 않습니다. Uni-proc 시스템에서는 성능이 절대적으로 끔찍합니다.
에반 테란

일반적으로 다중 프로세서 시스템에서만 스핀 락을 사용합니다.
ConcernedOfTunbridgeWells

SMP에서도 몇 번 회전 한 후 OS 지원 절전 / 깨우기로 돌아갑니다. (예 : Linux futex시스템 호출은 지연 시간이 짧은 사용자 공간 뮤텍스 / 세마포어 구현을 지원하기 위해 존재합니다. en.wikipedia.org/wiki/Futex ) 경합이없는 빠른 경로에서, 또는 리소스를 곧 사용할 수있게되면 시스템 호출. 그러나 바쁘게 기다리는 동안 몇 초를 소비하지 않습니다. 스핀 루프 백 오프 및 대기의 매개 변수 조정은 물론 하드웨어 및 작업 부하에 따라 다르지만 표준 라이브러리는 일반적으로 합리적인 선택이 있습니다.
Peter Cordes

19

뮤텍스 및 세마포어는 동기화 프리미티브로 사용되지만 이들 사이에는 큰 차이가 있습니다. 뮤텍스의 경우 뮤텍스를 잠 그거나 획득 한 스레드 만 잠금을 해제 할 수 있습니다. 세마포어의 경우, 세마포어를 기다리는 스레드는 다른 스레드에 의해 시그널링 될 수있다. 일부 운영 체제는 프로세스 간 뮤텍스 및 세마포어 사용을 지원합니다. 일반적으로 사용량은 공유 메모리에서 생성됩니다.


"다른 스레드에 의해 신호를받을 수있다"는 의미는 무엇입니까?
Myanju

15

Mutex : 임계 섹션 스레드 T1이 액세스하려는 경우 아래 단계를 따릅니다. T1 :

  1. 자물쇠
  2. 중요 섹션 사용
  3. 터놓다

이진 세마포어 : 신호 대기 및 신호를 기반으로 작동합니다. wait (s)는 "s"값을 1 씩 감소시킵니다. 일반적으로 "s"값은 "1"값으로 초기화되고, 신호는 "s"값을 1 씩 증가시킵니다. "s"값이 1이면 아무도 임계 섹션을 사용하고 있지 않고, 값이 0이면 임계 섹션이 사용 중임을 의미합니다. 스레드 T2가 임계 섹션을 사용하고 있다고 가정하면 아래 단계를 따릅니다. T2 :

  1. wait (s) // 처음 s 값은 wait 호출 후 1입니다. 값이 1 씩 감소합니다. 즉 0
  2. 중요 섹션 사용
  3. signal (s) // 이제 s 값이 증가하고 1이됩니다.

Mutex와 바이너리 세마포어의 주요 차이점은 스레드가 중요 섹션을 잠그면 중요 텍스트 섹션을 잠금 해제 해야하는 경우 Mutext에 있으며 다른 스레드는 잠금을 해제 할 수 없지만 바이너리 스레드의 경우 하나의 스레드가 대기 기능을 사용하여 중요 섹션을 잠그면 값 s의 값이 "0"이되고 "s"의 값이 1이 될 때까지 아무도 액세스 할 수 없지만 다른 스레드가 신호를 호출 한 다음 "s"의 값이 1이되고 다른 함수가 중요한 섹션을 사용할 수 있다고 가정합니다. 따라서 이진 세마포어 스레드에는 소유권이 없습니다.


12

Windows에서 뮤텍스와 이진 세마포어에는 두 가지 차이점이 있습니다.

  1. 뮤텍스는 소유권이있는 스레드, 즉 이전에 대기 기능을 호출 한 스레드 (또는 생성시 소유권을 가져온 스레드) 만 해제 할 수 있습니다. 모든 스레드에서 세마포어를 해제 할 수 있습니다.

  2. 스레드는 차단하지 않고 뮤텍스에서 대기 함수를 반복해서 호출 할 수 있습니다. 그러나 사이에 세마포어를 해제하지 않고 이진 세마포어에서 대기 함수를 두 번 호출하면 스레드가 차단됩니다.


4
좋은 대답입니다. # 2에서는 재귀 뮤텍스를 설명하고 있습니다. 모든 뮤텍스가 반드시 재귀적인 것은 아닙니다. 예 : cs.wustl.edu/~schmidt/ACE.FAQ.html#Q14
Dan

10

분명히 뮤텍스를 사용하여 한 스레드에서 다른 스레드가 동시에 액세스하는 데이터를 잠급니다. 방금 전화를 걸어 lock()데이터에 액세스하는 중이라고 가정하십시오 . 이것은 다른 스레드 (또는 동일한 스레드 코드의 다른 인스턴스)가 동일한 뮤텍스에 의해 잠긴 동일한 데이터에 액세스하지 않을 것을 의미합니다. 즉, 다른 스레드 인스턴스에서 동일한 스레드 코드가 실행되면 잠금을 누른 다음lock()제어 흐름을 차단해야합니다. 이것은 다른 스레드 코드를 사용하는 스레드에 적용되며, 동일한 스레드 코드에도 동일한 데이터에 액세스하고 동일한 뮤텍스에 의해 잠겨 있습니다. 이 경우 여전히 데이터에 액세스하는 과정에 있으며 뮤텍스 잠금 해제에 도달하는 데 15 초가 더 걸릴 수 있습니다. 데이터에 액세스). 다른 스레드가 동일한 뮤텍스를 잠금 해제하고 뮤텍스 잠금에서 이미 대기중인 (블로킹) 스레드가 데이터를 차단 해제하고 액세스 할 수 있도록 허용합니까? 내가 여기서 뭐라고하길 바래? 당연히 보편적 정의에 동의했다!

  • "뮤텍스"를 사용하면 이런 일이 발생할 수 없습니다. 다른 스레드는 스레드의 잠금을 해제 할 수 없습니다
  • "이진-세마포"를 사용하면 이런 일이 발생할 수 있습니다. 다른 스레드는 스레드의 잠금을 해제 할 수 있습니다

따라서 mutex 대신 binary-semaphore를 사용하는 것이 매우 중요하다면 잠금 및 잠금 해제의“범위 지정”에 매우주의해야합니다. 모든 잠금에 부딪힌 모든 제어 흐름은 잠금 해제 호출에 도달해야하며 "첫 번째 잠금 해제"도 없어야하며 항상 "첫 번째 잠금"이어야합니다.


10

뮤텍스는 "잠금 장치"에 사용됩니다. 한 번에 하나의 프로세스가 공유 리소스를 사용할 수 있습니다

이므로

세마포어는 "완료되었습니다. 이제 계속할 수 있습니다"와 같은 "신호 메커니즘"에 사용됩니다.


9

신화:

"이진 세마포어와 뮤텍스가 동일하다"또는 "값이 1 인 세마포어가 뮤텍스이다"라는 기본 기사는 Mutex를 획득 한 스레드 만 해제 할 수 있지만 다른 스레드에서 세마포어를 표시 할 수 있다는 기본적인 차이점은

키 포인트:

• 스레드는 둘 이상의 잠금 (Mutex)을 획득 할 수 있습니다.

• 재귀 뮤텍스, 뮤텍스에 대한 잠금 및 잠금 해제가 동일 해야하는 경우에만 뮤텍스를 두 번 이상 잠글 수 있습니다

• 이미 뮤텍스를 잠근 스레드가 뮤텍스를 다시 잠그려고하면 해당 뮤텍스의 대기 목록에 들어가 교착 상태가 발생합니다.

• 이진 세마포어와 뮤텍스는 비슷하지만 동일하지 않습니다.

• Mutex는 관련 보호 프로토콜로 인해 비용이 많이 듭니다.

• 뮤텍스의 주요 목표는 원자 적 액세스 또는 리소스 잠금을 달성하는 것입니다.


8

뮤텍스는 하나의 공유 리소스에 대한 액세스를 제어합니다. 해당 자원에 대한 액세스 를 확보 () 하고 완료되면 해제 () 하는 조작을 제공합니다 .

세마포어 자원의 공유 풀에 대한 액세스를 제어합니다. 풀의 자원 중 하나가 사용 가능해질 때까지 Wait () 및 풀에 다시 제공 될 때 Signal ()에 조작을 제공 합니다.

세마포가 보호하는 자원의 수가 1보다 크면이를 세마포어 계수 라고합니다 . 하나의 리소스를 제어 할 때 부울 세마포 라고합니다. . 부울 세마포어는 뮤텍스와 같습니다.

따라서 세마포어는 뮤텍스보다 더 높은 수준의 추상화입니다. 뮤텍스는 세마포어를 사용하여 구현할 수 있지만 다른 방법은 아닙니다.


6

수정 된 질문은 "Linux"에서 뮤텍스와 "이진"세마포어의 차이점은 무엇입니까?

답변 : 다음은 차이점입니다. – i) 범위 – 뮤텍스의 범위는 프로세스 주소 공간 내에 있으며 뮤텍스의 범위는 스레드를 동기화하는 데 사용됩니다. 세마포어는 프로세스 공간에서 사용될 수있는 반면 프로세스 간 동기화에 사용될 수 있습니다.

ii) 뮤텍스는 세마포어보다 가볍고 빠릅니다. Futex가 훨씬 빠릅니다.

iii) Mutex는 동일한 횟수만큼 해제해야한다는 조건으로 동일한 스레드에서 여러 번 성공적으로 획득 할 수 있습니다. 획득하려는 다른 스레드가 차단됩니다. 세마포어의 경우 동일한 프로세스가 다시 획득하려고하면 한 번만 획득 할 수 있으므로 차단됩니다.


i) 틀렸다. ii) 출처? iii) 다릅니다.
curiousguy

6

이진 세마포어와 뮤텍스의 차이점 : 소유권 : 현재 소유자가 아닌 사람도 세마포어에 신호를 보낼 수 있습니다. 소유자가 아니지만 다른 스레드에서 게시 할 수 있음을 의미합니다.

세마포어는 프로세스의 공용 속성으로, 소유자가 아닌 스레드가 게시 할 수 있습니다. 이 차이를 굵은 글자로 표시하십시오.


5

뮤텍스는 중요한 지역을 차단하는 데 일하지만 세마포는 중요한 일을합니다.


5

http://www.geeksforgeeks.org/archives/9102 에서 자세히 설명합니다.

Mutex리소스에 대한 액세스를 동기화하는 데 사용되는 잠금 메커니즘입니다. Semaphore신호 메커니즘입니다.

뮤텍스 대신 이진 세마포어를 사용하려는 경우 프로그래머에게 달려 있습니다.


4

뮤텍스에 소유자가 있다는 사실 외에도 두 객체는 ​​서로 다른 용도로 최적화 될 수 있습니다. 뮤텍스는 짧은 시간 동안 만 유지되도록 설계되었습니다. 이를 위반하면 성능이 저하되고 일정이 잘못 될 수 있습니다. 예를 들어, 실행중인 스레드는 다른 스레드가 이미 차단되어 있어도 뮤텍스를 획득 할 수 있습니다. 세마포어가 더 공정성을 제공하거나 여러 조건 변수를 사용하여 공정성을 강요 할 수 있습니다.


세마포어에 대해서는 공정성이 보장되지만 뮤텍스에는 그렇지 않은 경우는?
curiousguy

1
POSIX에 의해 깨어해야 스레드 특정 요구 사항이 sem_post()대한 SCHED_FIFOSCHED_RR(이 두 가지가 기본되지 않음) : 가장 높은 우선 순위의 스레드를, 같은 우선 순위가 가장 긴 대기 된 스레드와 다중이있는 경우. OpenSolaris는 정상적인 스케쥴링에서도이 FIFO 규칙을 어느 정도 따릅니다. glibc와 FreeBSD의 경우 간단한 뮤텍스 잠금 해제 (즉, 우선 순위 보호 또는 우선 순위 상속이 아님)와 세마포어 게시는 기본적으로 동일하며 객체를 잠금 해제 된 것으로 표시 한 다음 대기중인 스레드가있을 경우 커널을 호출하여 깨우도록합니다.
jilles

4

창에서 차이점은 다음과 같습니다. MUTEX : 대기 를 성공적으로 실행하는 프로세스 는 신호 를 실행해야 하며 그 반대도 마찬가지입니다. 이진 세마포어 : 서로 다른 프로세스 가 세마포어에서 대기 또는 신호 작업을 실행할 수 있습니다 .


4

이진 세마포어가 뮤텍스로 사용될 수 있지만, 뮤텍스는 뮤텍스를 잠근 프로세스 만 잠금을 해제해야한다는 점에서보다 구체적인 사용 사례입니다. 이 소유권 제약으로 다음에 대한 보호 기능을 제공 할 수 있습니다.

  • 실수로 릴리스
  • 재귀 교착 상태
  • 작업 죽음 교착 상태

이러한 제한은 속도를 저하시키기 때문에 항상 존재하는 것은 아닙니다. 코드를 개발하는 동안 이러한 검사를 일시적으로 활성화 할 수 있습니다.

예를 들어 뮤텍스에서 Error check 속성을 활성화 할 수 있습니다. EDEADLK같은 것을 두 번 잠그려고하거나 EPERM자신이 아닌 뮤텍스를 잠금 해제하면 뮤텍스 검사 오류가 반환 됩니다 .

pthread_mutex_t mutex;
pthread_mutexattr_t attr;
pthread_mutexattr_init (&attr);
pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
pthread_mutex_init (&mutex, &attr);

초기화되면 다음과 같이 코드에 이러한 검사를 배치 할 수 있습니다.

if(pthread_mutex_unlock(&mutex)==EPERM)
 printf("Unlock failed:Mutex not owned by this thread\n");

4

위의 게시물을 살펴본 후 개념이 명확했습니다. 그러나 몇 가지 남아있는 질문이있었습니다. 그래서이 작은 코드를 작성했습니다.

우리가 세마포어를 가져 가지 않고 주려고 할 때, 그것은 통과합니다. 그러나 뮤텍스를 가져 가지 않고 주려고하면 실패합니다. 나는 이것을 Windows 플랫폼에서 테스트했습니다. MUTEX를 사용하여 동일한 코드를 실행하려면 USE_MUTEX를 활성화하십시오.

#include <stdio.h>
#include <windows.h>
#define xUSE_MUTEX 1
#define MAX_SEM_COUNT 1

DWORD WINAPI Thread_no_1( LPVOID lpParam );
DWORD WINAPI Thread_no_2( LPVOID lpParam );

HANDLE Handle_Of_Thread_1 = 0;
HANDLE Handle_Of_Thread_2 = 0;
int Data_Of_Thread_1 = 1;
int Data_Of_Thread_2 = 2;
HANDLE ghMutex = NULL;
HANDLE ghSemaphore = NULL;


int main(void)
{

#ifdef USE_MUTEX
    ghMutex = CreateMutex( NULL, FALSE, NULL);
    if (ghMutex  == NULL) 
    {
        printf("CreateMutex error: %d\n", GetLastError());
        return 1;
    }
#else
    // Create a semaphore with initial and max counts of MAX_SEM_COUNT
    ghSemaphore = CreateSemaphore(NULL,MAX_SEM_COUNT,MAX_SEM_COUNT,NULL);
    if (ghSemaphore == NULL) 
    {
        printf("CreateSemaphore error: %d\n", GetLastError());
        return 1;
    }
#endif
    // Create thread 1.
    Handle_Of_Thread_1 = CreateThread( NULL, 0,Thread_no_1, &Data_Of_Thread_1, 0, NULL);  
    if ( Handle_Of_Thread_1 == NULL)
    {
        printf("Create first thread problem \n");
        return 1;
    }

    /* sleep for 5 seconds **/
    Sleep(5 * 1000);

    /*Create thread 2 */
    Handle_Of_Thread_2 = CreateThread( NULL, 0,Thread_no_2, &Data_Of_Thread_2, 0, NULL);  
    if ( Handle_Of_Thread_2 == NULL)
    {
        printf("Create second thread problem \n");
        return 1;
    }

    // Sleep for 20 seconds
    Sleep(20 * 1000);

    printf("Out of the program \n");
    return 0;
}


int my_critical_section_code(HANDLE thread_handle)
{

#ifdef USE_MUTEX
    if(thread_handle == Handle_Of_Thread_1)
    {
        /* get the lock */
        WaitForSingleObject(ghMutex, INFINITE);
        printf("Thread 1 holding the mutex \n");
    }
#else
    /* get the semaphore */
    if(thread_handle == Handle_Of_Thread_1)
    {
        WaitForSingleObject(ghSemaphore, INFINITE);
        printf("Thread 1 holding semaphore \n");
    }
#endif

    if(thread_handle == Handle_Of_Thread_1)
    {
        /* sleep for 10 seconds */
        Sleep(10 * 1000);
#ifdef USE_MUTEX
        printf("Thread 1 about to release mutex \n");
#else
        printf("Thread 1 about to release semaphore \n");
#endif
    }
    else
    {
        /* sleep for 3 secconds */
        Sleep(3 * 1000);
    }

#ifdef USE_MUTEX
    /* release the lock*/
    if(!ReleaseMutex(ghMutex))
    {
        printf("Release Mutex error in thread %d: error # %d\n", (thread_handle == Handle_Of_Thread_1 ? 1:2),GetLastError());
    }
#else
    if (!ReleaseSemaphore(ghSemaphore,1,NULL) )      
    {
        printf("ReleaseSemaphore error in thread %d: error # %d\n",(thread_handle == Handle_Of_Thread_1 ? 1:2), GetLastError());
    }
#endif

    return 0;
}

DWORD WINAPI Thread_no_1( LPVOID lpParam ) 
{ 
    my_critical_section_code(Handle_Of_Thread_1);
    return 0;
}


DWORD WINAPI Thread_no_2( LPVOID lpParam ) 
{
    my_critical_section_code(Handle_Of_Thread_2);
    return 0;
}

세마포어가 리소스를 소유 한 적이 없더라도 "리소스를 사용하여 완료되었습니다"라는 신호를 보낼 수 있다는 사실은 세마포어의 경우 소유와 신호 사이에 매우 느슨한 결합이 있다고 생각합니다.


다른 답변을 읽으면 "소유권"이라는 개념은 세마포어가 아닌 뮤텍스에만 의미가 있다는 것이 분명합니다. 세마포어 (semaphores)는 다른 스레드가 데이터 청크 처리가 완료되었음을 알리는 스레드와 같은 작업에 사용될 수 있습니다. 결과를 읽을 준비가되었습니다.
Peter Cordes

2

Mutex는 민감한 코드와 데이터를 보호하는 데 사용되고 세마포어는 동기화하는 데 사용됩니다. 또한 민감한 코드를 보호하는 데 실제로 사용할 수 있지만 V를 통해 다른 스레드의 보호를 해제 할 위험이있을 수 있습니다. 예를 들어 화장실, Mutex는 화장실에 들어가서 문을 잠글 수있는 것과 같으며, 사람이 나올 때까지 아무도 들어갈 수 없으며, Bi- 세마포어는 사람이 들어갈 수있는 것과 같습니다. 화장실을 열고 문을 잠그십시오. 그러나 다른 사람이 관리자에게 문을 열도록 요청하면 들어갈 수 있습니다.


2

뮤텍스

뮤텍스는 일반적으로 둘 이상의 스레드가 동시에 실행할 수없는 재진입 코드 섹션에 대한 액세스를 직렬화하는 데 사용됩니다. 뮤텍스 객체는 하나의 스레드를 제어 된 섹션으로 만 허용하여 해당 섹션에 액세스하려는 다른 스레드가 해당 섹션에서 첫 번째 스레드가 종료 될 때까지 대기하도록합니다. 의도하지 않은 부작용. 서로 다른 우선 순위로 작동하고 뮤텍스를 통해 조정되는 두 가지 RTOS 작업은 우선 순위 반전 의 기회를 만듭니다 . Mutex는 사용자 공간 에서 작동 합니다 .

신호기

세마포는 신호 메커니즘입니다. 세마포어는 공유 리소스의 동시 사용자 수를 최대 수로 제한합니다. 스레드는 리소스에 대한 액세스를 요청하고 (세마포 감소) 리소스 사용이 완료되었음을 알리는 (세마포 증가) 신호를 보낼 수 있습니다. 스레드 수는 공유 리소스에 액세스 할 수 있습니다. 세마포어의 올바른 사용은 한 작업에서 다른 작업으로 신호를 보내는 데 사용되며, 세마포어를 사용하여 인터럽트 서비스 루틴 (ISR)에서 작업 으로 신호를 보낼 수도 있습니다 . 세마포 신호는 비 차단 RTOS 동작이므로 ISR 안전합니다. 이 기술은 오류가 발생하기 쉬운 작업 수준에서 인터럽트를 비활성화 할 필요가 없으므로 커널 공간 에서 작동 합니다 .


1

대답은 대상 OS에 따라 다를 수 있습니다. 예를 들어, 내가 익숙한 하나 이상의 RTOS 구현은 모두 동일한 스레드 컨텍스트 내에서 단일 OS 뮤텍스에 대해 여러 개의 순차적 "get"작업을 허용합니다. 다른 스레드가 뮤텍스를 얻을 수 있으려면 여러 개의 get을 같은 수의 put으로 대체해야합니다. 스레드 컨텍스트와 상관없이 한 번에 하나의 get 만 허용되는 이진 세마포어와 다릅니다.

이 유형의 뮤텍스의 기본 개념은 한 번에 하나의 컨텍스트만으로 데이터를 수정하도록하여 객체를 보호한다는 것입니다. 스레드가 뮤텍스를 가져 와서 객체를 추가로 수정하는 기능을 호출하고 (자체 작업 주위에 보호기 뮤텍스를 가져 오거나 넣는) 작업은 모두 단일 스레드에서 발생하기 때문에 안전해야합니다.

{
    mutexGet();  // Other threads can no longer get the mutex.

    // Make changes to the protected object.
    // ...

    objectModify();  // Also gets/puts the mutex.  Only allowed from this thread context.

    // Make more changes to the protected object.
    // ...

    mutexPut();  // Finally allows other threads to get the mutex.
}

물론이 기능을 사용할 때는 단일 스레드 내의 모든 액세스가 실제로 안전해야합니다!

이 접근 방식이 얼마나 일반적인지 또는 내가 익숙한 시스템 외부에 적용되는지 확실하지 않습니다. 이러한 종류의 뮤텍스의 예는 ThreadX RTOS를 참조하십시오.


2
당신이 말하는 뮤텍스의 종류는 "재귀 뮤텍스 (recursive mutex)"라고 불립니다. 그것들은 느리고 나쁜 디자인을 조장하기 때문에 피해야합니다 : (David Butenhof : zaval.org/resources/library/butenhof1.html 참조 )
gaspard

동의했다. 이 특정 OS에서는 코드가 "상호 제외"용이며 참조 횟수가 아니라는 점을 분명히하기 위해 mutex 서비스를 사용하지만 추악한 풀림에 대한 두려움으로 재귀 기능을 사용하지 않습니다. 여전히, 질문의 맥락에서, 이것은 "뮤텍스"와 "이진 세마포어"사이의 중요한 차이입니다.
Casey Barker

1

뮤텍스는 세마포어와 달리 소유권을 갖습니다. 뮤텍스 범위 내에있는 스레드는 잠금 해제 된 뮤텍스를 가져와 동일한 중요 코드 섹션에 대한 액세스를 잠글 수 있지만 뮤텍스를 잠근 스레드 만 잠금을 해제 해야 합니다 .


당신은 뮤텍스를 얻는 컨텍스트가 단지 그것을 취득 할 수 없다는 것을 의미합니다.
Raulp

1

여기에서 많은 사람들이 언급했듯이 뮤텍스는 중요한 코드 조각 (AKA 임계 섹션)을 보호하는 데 사용됩니다. 뮤텍스 (잠금)를 획득하고 임계 섹션을 입력 한 다음 뮤텍스 (잠금 해제)를 모두 같은 스레드에서 해제 합니다 .

세마포어를 사용하는 동안 다른 스레드 (예 : 스레드 B)가 어떤 작업을 완료 할 때까지 스레드가 세마포어 (예 : 스레드 A)를 대기 한 다음 스레드 A의 세마포어를 설정하여 대기를 중지하고 작업을 계속할 수 있습니다.


1

최고의 솔루션

유일한 차이점은

1. Mutex-> 잠금 및 잠금 해제는 뮤텍스를 잠그는 스레드의 소유권입니다.

2. 세마포어-> 소유권 없음; 하나의 스레드가 semwait를 호출하면 다른 스레드는 sempost를 호출하여 잠금을 제거 할 수 있습니다.


1

뮤텍스

최근까지 커널에서 유일한 잠자기 잠금은 세마포어였습니다. 대부분의 세마포어 사용자는 세마포어를 1 개로 인스턴스화하여 상호 배제 잠금 (spin-lock의 수면 버전)으로 취급했습니다. 불행하게도, 세마포어는 다소 일반적이며 사용 제약을 부과하지 않습니다. 이는 커널과 사용자 공간 사이의 복잡한 춤과 같이 모호한 상황에서 독점 액세스를 관리하는 데 유용합니다. 그러나 이는 단순한 잠금이 더 어려워지고 시행 규칙이 없기 때문에 모든 종류의 자동 디버깅 또는 제약 조건 시행이 불가능하다는 것을 의미합니다. 보다 간단한 수면 잠금 장치를 찾기 위해 커널 개발자는 뮤텍스를 도입했습니다. "뮤텍스"라는 용어는 상호 배제를 강제하는 모든 수면 잠금 장치를 지칭하는 일반적인 이름입니다. 사용량이 1 인 세마포어와 같은 최근 Linux 커널에서 올바른 명사“mutex”는 이제 상호 배제를 구현하는 특정 유형의 수면 잠금 장치입니다. 즉, mutex는 mutex입니다.

뮤텍스의 단순성과 효율성은 세마포어가 요구하는 것 이상으로 사용자에게 부과하는 추가 제약에서 비롯됩니다. Dijkstra의 독창적 인 디자인에 따라 가장 기본적인 동작을 구현하는 세마포어와 달리 뮤텍스는 더 엄격하고 좁은 사용 사례를 갖습니다. n 한 번에 하나의 작업 만 뮤텍스를 유지할 수 있습니다. 즉, 뮤텍스의 사용량은 항상 하나입니다.

  1. 뮤텍스를 잠근 사람은 반드시 잠금을 해제해야합니다. 즉, 한 컨텍스트에서 뮤텍스를 잠근 다음 다른 컨텍스트에서 잠금을 해제 할 수 없습니다. 이는 뮤텍스가 커널과 사용자 공간 간의보다 복잡한 동기화에 적합하지 않음을 의미합니다. 그러나 대부분의 사용 사례는 동일한 컨텍스트에서 완전히 잠그고 잠금을 해제합니다.
  2. 재귀 잠금 및 잠금 해제는 허용되지 않습니다. 즉, 동일한 뮤텍스를 재귀 적으로 획득 할 수 없으며 잠금 해제 된 뮤텍스를 잠금 해제 할 수 없습니다.
  3. 뮤텍스를 잡고있는 동안 프로세스를 종료 할 수 없습니다.
  4. mutex_trylock ()을 사용하더라도 인터럽트 처리기 또는 하단 절반에서 뮤텍스를 가져올 수 없습니다.
  5. 뮤텍스는 공식 API를 통해서만 관리 할 수 ​​있습니다.이 섹션에 설명 된 방법을 통해 초기화해야하며 복사, 수작업 초기화 또는 다시 초기화 할 수 없습니다.

[1] 리눅스 커널 개발, 제 3 판 Robert Love


1

나는 뮤텍스가 그것을 보유하고있는 프로세스에 의해서만 릴리스 될 수 있지만 세마포어는 ay 프로세스에 의해 시그널링 될 수 있다고 말하는 사람들의 대답이 혼란 스럽다고 생각합니다. 위의 줄은 세마포어 측면에서 모호합니다. 이해하기 위해 세마포어에는 두 가지 종류가 있으며, 하나는 카운팅 세마포어이고 다른 하나는 이진 세마포어입니다. 계산에서 세마포어는 사용하기 전에 n을 정의 할 수있는 n 개의 리소스에 대한 액세스를 처리합니다. 각 세마포어에는 count 변수가 있습니다.이 변수는 사용중인 리소스 수의 개수를 유지하며 처음에는 n으로 설정됩니다. 리소스를 사용하려는 각 프로세스는 세마포어에서 wait () 작업을 수행하여 카운트를 줄입니다. 프로세스가 자원을 해제하면 release () 작업을 수행합니다 (카운트 증가). 카운트가 0이되면 모든 자원이 사용되고 있습니다. 그 후, 프로세스는 계수가 0보다 커질 때까지 대기합니다. 이제 자원을 보유하는 프로세스 만이 계수를 증가시킬 수 있습니다. 다른 프로세스는 계수를 증가시킬 수 없습니다. 자원을 보유한 프로세스 만이 계수를 증가시킬 수 있습니다. 세마포어를 다시 확인하면 사용 가능한 리소스가 표시되면 카운트가 다시 줄어 듭니다. 따라서 이진 세마포어 측면에서 세마포어를 보유한 프로세스 만 카운트를 증가시킬 수 있으며, 세마포어 사용을 중지하고 카운트를 증가시킬 때까지 카운트는 0으로 유지되며 다른 프로세스는 세마포어에 액세스 할 수 있습니다. 이제는 리소스를 보유한 프로세스 만 카운트를 늘릴 수 있습니다. 다른 프로세스는 카운트를 늘릴 수 없습니다. 리소스를 보유한 프로세스 만 카운트를 늘릴 수 있고 세마포어를 다시 기다리는 프로세스는 리소스를 사용할 수있을 때 볼 수 있습니다 카운트를 다시 줄입니다. 따라서 이진 세마포어 측면에서 세마포어를 보유한 프로세스 만 카운트를 증가시킬 수 있으며, 세마포어 사용을 중지하고 카운트를 증가시킬 때까지 카운트는 0으로 유지되며 다른 프로세스는 세마포어에 액세스 할 수 있습니다. 이제는 리소스를 보유한 프로세스 만 카운트를 늘릴 수 있습니다. 다른 프로세스는 카운트를 늘릴 수 없습니다. 리소스를 보유한 프로세스 만 카운트를 늘릴 수 있고 세마포어를 다시 기다리는 프로세스는 리소스를 사용할 수있을 때 볼 수 있습니다 카운트를 다시 줄입니다. 따라서 이진 세마포어 측면에서 세마포어를 보유한 프로세스 만 카운트를 증가시킬 수 있으며, 세마포어 사용을 중지하고 카운트를 증가시킬 때까지 카운트는 0으로 유지되며 다른 프로세스는 세마포어에 액세스 할 수 있습니다.

이진 세마포어와 뮤텍스의 주요 차이점은 세마포어가 신호 메커니즘이고 뮤텍스가 잠금 메커니즘이지만 이진 세마포어는 혼동을 일으키는 뮤텍스처럼 작동하는 것 같지만 둘 다 다른 종류의 작업에 적합한 다른 개념입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.