it-swarm-ko.tech

바이너리 세마포어와 뮤텍스의 차이점

바이너리 세마포어와 뮤텍스간에 차이가 있습니까? 아니면 본질적으로 동일합니까?

741
Nitin

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

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

뮤텍스 세마포는 그것을 가져가는 작업에 의해 "소유"됩니다. 작업 B가 현재 작업 A에 의해 보유 된 뮤텍스를 semGive하려고하면, 작업 B의 호출은 오류를 반환하고 실패합니다.

뮤텍스는 항상 다음 시퀀스를 사용합니다.

 - SemTake 
 - 중요 섹션 
 - SemGive

다음은 간단한 예입니다.

 스레드 A 스레드 B 
 뮤텍스 가져 오기 
 액세스 데이터 
 ... 뮤텍스 가져 오기 <== 차단할 것입니다. 
 ... 
 뮤텍스에 데이터 접근하기 <== 차단 해제 
 ... 
 뮤텍스 
를줍니다.

바이너리 세마포어
바이너리 세마포어는 완전히 다른 질문을 다룹니다.

  • 작업 B는 어떤 일이 일어날 때까지 대기합니다 (예 : 센서가 트립 됨).
  • 센서 트립 및 인터럽트 서비스 루틴이 실행됩니다. 여행의 임무를 알릴 필요가 있습니다.
  • 작업 B가 실행되어 센서 트립에 적절한 조치를 취해야합니다. 그런 다음 기다리십시오.

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

바이너리 세마포어를 사용하면 B가 세마포어를 가져오고 A가 세마포어를 가져 오는 것이 좋습니다.
바이너리 세마포어는 자원을 액세스로부터 보호하지 못합니다. 주기적으로 세마포어를주고받는 행위는 기본적으로 분리됩니다.
같은 작업이 동일한 바이너리 세마포어를주고받는 것이 일반적으로 거의 의미가 없습니다.

635
Benoit

화장실의 예 는 즐거운 비유입니다.

뮤텍스 :

화장실 열쇠입니다. 한 사람이 그 열쇠를 가질 수 있습니다 - 당시 화장실을 차지하십시오 -. 작업이 끝나면 대기열의 다음 사람에게 키를 제공 (해제)합니다.

공식적으로 "뮤텍스는 일반적으로 둘 이상의 스레드가 동시에 실행할 수없는 재진입 코드 섹션에 대한 액세스를 직렬화하는 데 사용됩니다. 뮤텍스 개체는 제어 섹션에 하나의 스레드 만 허용하여 다른 스레드가 액세스를 시도합니다 그 섹션은 첫 번째 스레드가 그 섹션에서 빠져 나갈 때까지 기다려야합니다. " 심판 : 심비안 개발자 라이브러리

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

신호기:

무료로 사용 가능한 동일한 변기 수입니다. 예를 들어, 동일한 자물쇠와 열쇠가있는 화장실이 4 개 있다고 가정 해보십시오. 세마포어 카운트 - 키 수 -는 처음에 4로 설정되고 (네 개의 화장실 모두 사용 가능), 사람들이 들어올 때 카운트 값이 감소합니다. 모든 화장실이 가득 찼다면 즉, 여유 키가 남아 있지 않습니다. 세마포어 수는 0입니다. 이제, eq. 한 사람이 변기를 떠나고, 세마포어가 1 (무료 키 하나)로 증가하고 대기열의 다음 사람에게 제공됩니다.

공식적으로 : "세마포어는 공유 리소스의 동시 사용자 수를 최대 수로 제한하며 스레드는 리소스에 대한 액세스를 요청할 수 있고 (세마포를 감소 시킴) 리소스 사용을 완료했다는 신호를 보낼 수 있습니다 (세마포어 증가). " 심판 : 심비안 개발자 라이브러리

416
dlinsin

뮤텍스는 다른 스레드 (또는 프로세스)에서 세마포어를 신호로 보낼 수있는 동안 획득 한 스레드에 의해서만 릴리스 될 수 있으므로 세마포어는 생산자 - 소비자와 같은 일부 동기화 문제에 더 적합합니다.

Windows에서 바이너리 세마포어는 뮤텍스보다 이벤트 객체에 가깝습니다.

411
Mladen Janković

주제에 대한 좋은 기사 :

파트 2에서 :

뮤텍스는 바이너리 세마포어의 원리와 비슷하지만 하나의 중요한 차이점이 있습니다 : 소유권의 원칙. 소유권은 태스크가 뮤텍스를 잠그는 (획득하는) 경우에만 잠금 해제 (해제) 할 수 있다는 단순한 개념입니다. 작업이 잠긴 적이없는 (따라서 소유하지 않은) 뮤텍스를 잠금 해제하려고 시도하면 오류 조건이 발생하며 가장 중요한 것은 뮤텍스가 잠금 해제되어 있지 않다는 것입니다. 상호 배제 객체가 소유권을 가지지 않는다면, 상호 배제 객체는 뮤텍스가 아니다.

139
teki

위의 답변 중 어느 것도 혼란을 없애지 않으므로 여기에 내 혼란을 없애주는 답변이 있습니다.

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

세마포어는 신호 메커니즘입니다. ( "끝났습니다. 계속 진행할 수 있습니다"라는 신호). 예를 들어 휴대 전화에서 노래를 듣고 (하나의 작업으로 가정) 친구가 전화를받는 동시에 인터럽트가 발생하여 ISR (인터럽트 서비스 루틴)이 통화 처리 작업을 깨우기 위해 신호를 보냅니다 .

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

92
Hemant

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

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

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

39
ppi
  • 정의에 따라 A Mutex 는 하나 이상의 스레드가 동시에 실행할 수없는 재진입 코드 섹션에 대한 액세스를 직렬화하는 데 사용됩니다.

  • A Semaphore 는 정의상 공유 자원의 동시 사용자 수를 최대 수로 제한합니다

  • 세마포어는 뮤텍스 일 수 있지만 뮤텍스는 절대로 세마포어가 될 수 없습니다. 이것은 바이너리 세마포어가 뮤텍스로 사용될 수 있다는 것을 의미하지만, 뮤텍스는 절대로 세마포어의 기능을 나타낼 수 없습니다.

  • 세마포어 (semaphore)와 뮤텍스 (Mutex) (적어도 최신 커널에서)는 본질적으로 비 재귀 적입니다.
  • 누구도 세마포를 소유하고 있지 않지만 뮤텍스는 소유하고 소유자는 자신에 대한 책임이 있습니다. 이는 디버깅 관점에서 중요한 차이점입니다.
  • 뮤텍스의 경우 뮤텍스를 소유 한 스레드가 뮤텍스를 해제해야합니다. 그러나 세마포어의 경우이 조건은 필요하지 않습니다. 다른 스레드는 s m p s (function.e_ot)를 사용하여 세마포어를 해제하도록 신호를 보낼 수 있습니다.

  • 개발자에게 중요한 또 다른 차이점은 세마포어는 시스템 전체에 적용되며 정리되지 않은 한 파일 시스템에 파일 형식으로 유지된다는 것입니다. 뮤텍스는 프로세스 전체에 적용되며 프로세스가 종료되면 자동으로 정리됩니다.

  • 세마포어의 본질은 관련된 스레드와 관련이없는 프로세스는 물론 스레드 간의 동기화에도 사용할 수 있습니다. 뮤텍스는 스레드 간의 동기화와 관련된 프로세스 사이에서만 가능합니다 (최신 커널의 pthread 구현에는 관련된 프로세스간에 Mutex를 사용할 수있는 기능이 있습니다).
  • 커널 문서에 따르면, 뮤텍스는 세마포어에 비해 가볍습니다. 즉, 뮤텍스가있는 프로그램과 비교할 때 세마포어 사용량이 많은 프로그램의 메모리 사용량이 더 많습니다.
  • 사용 관점에서 뮤텍스는 세마포어와 비교할 때보다 간단한 의미 체계를가집니다.
35
Varun Chhangani

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

실질적인 차이 (그들을 둘러싼 시스템 서비스의 관점에서)는 뮤텍스의 구현이보다 가벼운 동기화 메커니즘이라는 것을 목표로한다는 것입니다. Oracle-speak에서 뮤텍스는 latches 이고 세마포어는 waits 입니다.

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

일반적인 뮤텍스 구현에는 테스트 및 설정 명령을 실행하고 뮤텍스를 설정 한 다른 항목이 있는지 평가하는 프로세스 또는 스레드가 있습니다. 여기서 중요한 점은 scheduler 와 상호 작용하지 않으므로 누가 잠금을 설정했는지 알 수 없습니다. 그런 다음 작업 시간을 다시 예약하거나 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'를 의미하는 것으로 설정하면됩니다. 여러 작업이 뮤텍스를 얻으려고 시도하는 경우 뮤텍스가 릴리스 된 후 예약 된 다음 작업은 리소스에 액세스 할 수 있습니다. 일반적으로 뮤텍스를 사용하여 독점 액세스가 매우 짧은 시간 동안 만 필요한 경우 일반적으로 공유 데이터 구조를 업데이트하는 동기화 된 리소스를 제어합니다.

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

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

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

21

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

18
Praveen_Shukla

뮤텍스 : 임계 영역 스레드 T1이 액세스하려고한다고 가정하고 다음 단계를 수행합니다. T1 :

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

바이너리 세마포어 : 신호 대기 및 신호를 기반으로 작동합니다. 대기 "s"값을 1 씩 감소시킵니다. "s"값은 값 "1"로 초기화되고, 신호는 "s"값을 1 씩 증가시킵니다. "s"값이 1이면 아무도 임계 구역을 사용하지 않고, 값이 0이면 임계 구역이 사용 중임을 의미합니다. 쓰레드 T2가 critical section을 사용하고 있다고 가정하면, 그것은 아래 단계를 따른다. T2 :

  1. wait (s) // 초기 값은 호출 후 하나입니다. wait 값은 1만큼 감소합니다. 즉 0입니다.
  2. 임계 영역 사용
  3. signal (s) // 이제 s 값이 증가하고 1이됩니다.

뮤텍스와 바이너리 세마포어의 주요 차이점은 스레드가 크리티컬 섹션을 잠그면 크리티컬 섹션을 잠금 해제해야한다. 다른 스레드는 잠금을 해제 할 수 없다.하지만 바이너리 세마포어의 경우 한 스레드가 대기 (잠김) 함수를 사용하여 중요한 섹션을 잠그면 값 s의 값이 1이 될 때까지 아무도 접근 할 수 없지만 다른 스레드가 신호를 호출하면 "s"의 값이 1이되고 다른 기능이 임계 영역을 사용할 수있게합니다. 따라서 바이너리 세마포어 스레드에는 소유권이 없습니다.

11
Sumit Naik

분명히 mutex를 사용하여 한 스레드의 데이터를 다른 스레드가 동시에 액세스 할 수 있도록 잠급니다. 방금 lock()을 호출했으며 데이터에 액세스하는 중이라고 가정합니다. 이는 다른 스레드 (또는 동일한 스레드 코드의 다른 인스턴스)가 동일한 뮤텍스에 의해 잠긴 동일한 데이터에 액세스하는 것을 기대하지 않는다는 것을 의미합니다. 즉, 다른 스레드 인스턴스에서 실행중인 동일한 스레드 코드가 잠금을 초과하면 lock()이 제어 흐름을 차단해야합니다. 이것은 동일한 스레드 코드를 사용하는 스레드에 적용됩니다.이 스레드 코드는 동일한 데이터에 액세스하고 있으며 동일한 뮤텍스에 의해 잠겨 있습니다. 이 경우에도 데이터 액세스 프로세스가 진행 중이고 다른 15 초 동안 뮤텍스 잠금 해제에 도달 할 수 있습니다 (따라서 뮤텍스 잠금으로 차단 된 다른 스레드는 차단 해제되어 제어가 허용됩니다). 데이터에 액세스). 어떤 비용으로도 다른 스레드가 동일한 뮤텍스를 잠금 해제 할 수있게하고 뮤텍스 잠금에서 이미 대기중인 (차단) 스레드가 데이터를 차단 해제하고 액세스하도록 허용합니까? 내가 여기서 말하는 것을 가지고 있기를 바랍니다. 당연히, 보편적 인 정의에 합의했습니다!

  • "뮤텍스 (mutex)"로는 이런 일이 일어날 수 없다. 다른 스레드가 스레드의 잠금을 해제 할 수 없습니다.
  • "binary-semaphore"가 발생합니다. 다른 스레드가 스레드의 잠금을 해제 할 수 있습니다.

따라서 뮤텍스 대신 바이너리 세마포어를 사용하는 것이 매우 중요하다면 잠금 및 잠금 해제의 "범위 지정"에 매우주의해야합니다. 모든 잠금을 치는 모든 제어 흐름이 잠금 해제 호출에 충돌해야하며 "첫 번째 잠금 해제"가 없어야하며 항상 "첫 번째 잠금"이어야합니다.

10
paxi

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

이므로

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

10
Jamshad Ahmad

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

  1. 뮤텍스는 소유권이있는 스레드, 즉 이전에 대기 함수를 호출 한 스레드 (또는 스레드를 생성 할 때 소유권을 가졌던 스레드)에 의해서만 릴리스 될 수 있습니다. 세마포어는 모든 스레드에 의해 해제 될 수 있습니다.

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

10
Rich

신화:

문서의 몇 가지는 "바이너리 세마포어와 뮤텍스는 동일합니다"또는 "값 1을 갖는 세마포어는 뮤텍스입니다."하지만 기본적인 차이점은 뮤텍스는 다른 스레드에서 세마포어를 신호로 보낼 수있는 반면 뮤텍스는이를 획득 한 스레드에서만 해제 할 수 있다는 것입니다

키 포인트:

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

• 뮤텍스는 반복적 인 뮤텍스, 여기서 뮤텍스에 대한 잠금 및 잠금 해제가 동일해야만 한 번 이상 잠길 수 있습니다

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

바이너리 세마포어와 뮤텍스는 유사하지만 동일하지 않습니다.

• 뮤텍스는 관련된 보호 프로토콜로 인해 값 비싼 작동입니다.

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

9
Saurabh Sinha

mutex은 단일 공유 자원에 대한 액세스를 제어합니다. 완료되면 acquire (} _ 그 자원에 대한 액세스와 release (} 작업을 제공합니다.

세마포은 공유 자원 풀에 대한 액세스를 제어합니다. 풀의 리소스 중 하나가 사용 가능해질 때까지 Wait () 연산을 제공하고, 풀에 리소스가 반환 될 때 Signal (} _ 연산을 제공합니다.

세마포어가 보호하는 자원의 수가 1보다 큰 경우 세마포 계산이라고합니다. 하나의 리소스를 제어 할 때 부울 세마포어라고합니다. 부울 세마포어는 뮤텍스와 동일합니다.

따라서 세마포는 뮤텍스보다 높은 수준의 추상화입니다. 뮤텍스는 세마포어를 사용하여 구현 될 수 있지만 그 반대의 경우는 아닙니다.

8
Charan

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

Ans : 다음은 차이점입니다. i) 범위 - 뮤텍스의 범위는 스레드를 생성하고 스레드 동기화에 사용되는 프로세스 주소 공간 내에 있습니다. 세마포어는 프로세스 공간에서 사용될 수 있기 때문에 프로세스 간 동기화에 사용될 수 있습니다.

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

iii) 동일한 스레드에 의해 뮤텍스가 여러 번 성공적으로 획득 될 수있다. 획득을 시도하는 다른 스레드가 차단됩니다. 세마포어의 경우 동일한 프로세스가 다시 세마포어를 획득하려고 시도하면 세마포어는 한 번만 획득 할 수 있으므로 차단합니다.

6
Mickey

임계 영역 차단에 대한 뮤텍스 작업. 그러나 세마포어는 계산에 영향을 미칩니다.

6
Askkan

바이너리 세마포어와 뮤텍스 사이의 차이 : 소유권 : 세마포어는 비 주류 소유자로부터조차도 신호 (게시) 할 수 있습니다. 소유자가 아니지만 다른 스레드에서 게시 할 수 있음을 의미합니다.

세마포어는 진행중인 공용 속성이며 비 소유자 스레드가 게시 할 수 있습니다. 이 차이점을 굵은 글씨로 표시하십시오.

5
buddingspacer

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

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

Mutex 대신에 바이너리 세마포어를 사용하고자한다면 프로그래머에게 달려있다.

5
user1852497

창문의 차이점은 아래와 같습니다. 성공적으로 wait을 실행해야하는 MUTEX : 프로세스는 signal을 실행해야하며, 그 반대도 마찬가지입니다. BINARY SEMAPHORES : 서로 다른 프로세스는 세마포어에서 wait 또는 signal 연산을 실행할 수 있습니다.

4
ajay bidari

Mutex에 소유자가 있다는 사실 외에도 두 객체는 ​​서로 다른 용도로 최적화 될 수 있습니다. 뮤텍스는 짧은 시간 동안 만 개최되도록 설계되었습니다. 이를 위반하면 성능 저하 및 불공정 한 스케줄링이 발생할 수 있습니다. 예를 들어, 실행중인 스레드는 다른 스레드가 이미 차단되어 있어도 뮤텍스를 획득하도록 허용 될 수 있습니다. 세마포어는보다 공정한 정보를 제공 할 수 있으며 공정성은 여러 조건 변수를 사용하여 강제 할 수 있습니다.

4
jilles

위의 게시물을 살펴본 후에 개념은 분명했습니다. 그러나 느린 질문이있었습니다. 그래서이 작은 코드를 썼습니다.

우리가 그것을 취하지 않고 세마포어를하려고 할 때, 그것은 통과합니다. 그러나 뮤텍스를 가져 오지 않고 뮤텍스를 제공하려고하면 실패합니다. 나는 이것을 Windows 플랫폼에서 테스트했다. USE_MUTEX가 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;
}
4
Raghav Navada

바이너리 세마포어는 뮤텍스로 사용될 수 있지만, 뮤텍스는 잠겨있는 프로세스 만 잠금을 해제해야한다는 점에서보다 구체적인 유스 케이스입니다. 이 소유권 제약은 다음에 대한 보호를 제공 할 수 있습니다.

  • 우발적 인 석방
  • 재귀 적 교착 상태
  • 작업 죽음 교착 상태

이러한 제한 조건은 속도를 떨어 뜨리기 때문에 항상 존재하지는 않습니다. 코드를 개발하는 동안 이러한 검사를 일시적으로 사용할 수 있습니다.

예 : 뮤텍스에서 오류 검사 속성을 활성화 할 수 있습니다. 뮤텍스 검사 오류는 동일한 항목을 두 번 고정하려고 시도하면 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");
3
Adi06411

뮤텍스는 민감한 코드와 데이터를 보호하기 위해 사용되며, 세마포어는 동기화에 사용됩니다. 또한 민감한 코드를 보호하여 실제 사용을 할 수 있지만 작업에 의한 다른 스레드의 보호를 해제 할 위험이있을 수 있습니다. 바이 - 세마포어와 뮤텍스의 차이점은 소유권입니다. 예를 들어, 화장실에서 뮤텍스는 변기에 들어가서 문을 잠그는 것과 같습니다. 아무도 나올 때까지 아무도 들어갈 수 없습니다. 바이 세마포어는 들어갈 수 있습니다. 화장실을 열고 문을 잠그지 만 다른 누군가는 관리자에게 문을 열어달라고 요청할 수 있습니다. 그것은 우스꽝 스럽습니다.

2
mannnnerd

뮤트

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

세마포어

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

1
Gopika BG

뮤텍스는 세마포어와 달리 소유권을 갖습니다. 뮤텍스의 범위 내에서 어떤 스레드라도 잠금 해제 된 뮤텍스를 얻을 수 있으며 동일한 중요 코드 섹션에 액세스 할 수 있지만 뮤텍스를 잠근 스레드 만 should = 잠금을 해제하십시오 .

1
laksbv

뮤텍스 (Mutex)와 바이너리 세마포어 (binary semaphore)는 둘 다 같은 용도이지만 실제로는 다르다.

뮤텍스의 경우 잠긴 스레드 만 잠금을 해제 할 수 있습니다. 다른 스레드가 잠기면 잠시 기다립니다.

세마 폰의 경우에는 그렇지 않습니다. 세마포어는 특정 스레드 ID로 묶이지 않습니다.

1
Neeraj Sh

대답은 대상 OS에 따라 다를 수 있습니다. 예를 들어, 내가 익숙한 적어도 하나의 RTOS구현은 동일한 스레드 컨텍스트 내에서 하나 인 한 개의 OS 뮤텍스에 대해 여러 개의 순차적 "get"연산을 허용합니다. 다른 thread가 뮤텍스를 취득하기 전에, 복수의 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를 참조하십시오.

1
Casey Barker

많은 사람들이 언급했듯이 뮤텍스는 중요한 코드 조각 (일명 중요한 섹션)을 보호하는 데 사용됩니다. 뮤텍스 (잠금), 중요 섹션 입력 및 뮤텍스 해제 (잠금 해제) 모두 같은 스레드.

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

1
Dom045

기본적인 문제는 동시성입니다. 제어 흐름이 둘 이상 있습니다. 공유 메모리를 사용하는 두 가지 프로세스를 생각해보십시오. 이제 한 번에 하나의 프로세스 만 공유 메모리에 액세스 할 수 있습니다. 한 번에 둘 이상의 프로세스가 공유 메모리에 액세스하면 공유 메모리의 내용이 손상됩니다. 철도 선로와 같습니다. 한 열차 만 운행 할 수 있으며, 그렇지 않으면 사고가 발생할 수 있으므로 운전자가 확인하는 신호 메커니즘이 있습니다. 신호가 녹색이면 열차가 운행되며 빨간색이면 트랙을 사용하기 위해 대기해야합니다. 마찬가지로 공유 메모리의 경우 이진 세마포가 있습니다. 세마포어가 1이면 프로세스가이를 확보하여 (0으로 설정) 계속 진행합니다. 세마포어가 0이면 프로세스가 대기합니다. 이진 세마포어가 제공해야하는 기능은 상호 배제 (또는 짧은 뮤텍스)이므로 많은 동시 엔티티 (프로세스 또는 스레드) 중 하나만 상호 배제합니다. 리소스의 여러 인스턴스를 동기화하는 데 도움이되는 세마포어를 세는 것이 플러스입니다.

상호 배제는 세마포어가 제공하는 기본 기능입니다. 이제 스레드의 맥락에서 우리는 다른 이름과 구문을 가질 수 있습니다. 그러나 기본 개념은 동일합니다. 동시 프로그래밍에서 코드와 데이터의 무결성을 유지하는 방법입니다. 제 생각에는 소유권 및 관련 점검과 같은 것들이 구현에 의해 제공되는 개선입니다.

0
kjohri

"바이너리 세마포어 (binary semaphore)"는"mutex"와 같은"세마포어"를 사용하지 못하도록하는 프로그래밍 언어입니다. 분명히 두 가지 큰 차이점이 있습니다.

  1. 당신이 그들 각자를 부르는 방식.

  2. "식별자"의 최대 길이.

0
ilias iliadis