programing

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

nasanasas 2020. 9. 29. 07:54
반응형

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


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


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

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

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

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

  -SemTake
  -중요 섹션
  -SemGive

다음은 간단한 예입니다.

  스레드 A 스레드 B
   뮤텍스 복용
     데이터 액세스
     ... 뮤텍스 가져 오기 <== 차단됨
     ...
   Mutex 액세스 데이터 제공 <== 차단 해제
                                  ...
                                뮤텍스 제공

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

  • 태스크 B는 어떤 일이 발생하기를 기다리고 있습니다 (예 : 센서가 트립 됨).
  • 센서 트립 및 인터럽트 서비스 루틴이 실행됩니다. 여행 작업을 알려야합니다.
  • 작업 B는 센서 트립에 대해 실행되고 적절한 조치를 취해야합니다. 그런 다음 다시 기다리십시오.

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

이진 세마포어를 사용하면 B가 세마포어를 사용하고 A가이를 제공하는 것이 좋습니다.
다시 말하지만, 바이너리 세마포어는 액세스로부터 리소스를 보호하지 않습니다. 세마포어를주고받는 행위는 근본적으로 분리되어 있습니다.
일반적으로 동일한 작업이 동일한 이진 세마포어를주고받는 것은 거의 의미가 없습니다.


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

뮤텍스 :

화장실의 열쇠입니다. 한 사람이 열쇠를 가질 수 있습니다 (화장실 점유). 완료되면 그 사람은 대기열에있는 다음 사람에게 키를 제공 (해제)합니다.

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

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

신호기:

Is the number of free identical toilet keys. Example, say we have four toilets with identical locks and keys. The semaphore count - the count of keys - is set to 4 at beginning (all four toilets are free), then the count value is decremented as people are coming in. If all toilets are full, ie. there are no free keys left, the semaphore count is 0. Now, when eq. one person leaves the toilet, semaphore is increased to 1 (one free key), and given to the next person in the queue.

Officially: "A semaphore restricts the number of simultaneous users of a shared resource up to a maximum number. Threads can request access to the resource (decrementing the semaphore), and can signal that they have finished using the resource (incrementing the semaphore)." Ref: Symbian Developer Library


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

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


주제에 대한 좋은 기사 :

2 부 :

뮤텍스는 이진 세마포어의 원칙과 비슷하지만 한 가지 중요한 차이점은 소유권 원칙입니다. 소유권은 작업이 뮤텍스를 잠그 (취득) 할 때만 잠금을 해제 (해제) 할 수 있다는 간단한 개념입니다. 태스크가 잠기지 않은 (따라서 소유하지 않은) 뮤텍스를 잠금 해제하려고하면 오류 조건이 발생하며 가장 중요한 것은 뮤텍스가 잠금 해제되지 않는다는 것입니다. 상호 배제 개체에 소유권이 없으면 호출되는 내용과 관계없이 뮤텍스가 아닙니다.


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

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

Semaphore는 신호 메커니즘입니다 ( "I am done, you can carry on"일종의 신호). 예를 들어, 모바일에서 노래를 듣고 (하나의 작업으로 가정) 친구가 전화를했을 때 인터럽트가 트리거되어 ISR (인터럽트 서비스 루틴)이 호출 처리 작업을 깨우도록 신호합니다. .

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


동기화 의미는 매우 다릅니다.

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

따라서 뮤텍스는 작업에서 작업으로 전달되는 토큰으로, 세마포어는 트래픽 레드 라이트 ( 진행할 수 있다는 신호 )로 볼 수 있습니다.


  • 뮤텍스는 , 정의에 의해, 둘 이상의 스레드가 동시에 실행되지 않을 수 재진입 코드 섹션 직렬화에 액세스하는데 사용된다.

  • 세마포어는 , 정의에 의해, 최대 수에 공유 리소스의 최대 동시 사용자들의 수를 제한

  • 세마포어는 뮤텍스가 될 수 있지만 뮤텍스는 세마포어가 될 수 없습니다. 이것은 단순히 이진 세마포어를 뮤텍스로 사용할 수 있지만 뮤텍스는 세마포어의 기능을 결코 보여줄 수 없음을 의미합니다.

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

  • 개발자에게 중요한 또 다른 차이점은 세마포어가 시스템 전체에 적용되며 별도로 정리하지 않는 한 파일 시스템의 파일 형태로 남아 있다는 것입니다. Mutex는 프로세스 전체에 적용되며 프로세스가 종료되면 자동으로 정리됩니다.

  • 세마포어의 특성으로 인해 관련 프로세스와 관련되지 않은 프로세스를 동기화 할 때뿐만 아니라 스레드 간에도 사용할 수 있습니다. Mutex는 스레드 간 및 관련 프로세스 간 동기화에만 사용할 수 있습니다 (최신 커널의 pthread 구현에는 관련 프로세스간에 Mutex를 사용할 수있는 기능이 함께 제공됩니다).
  • 커널 문서에 따르면 Mutex는 세마포어와 비교할 때 더 가볍습니다. 이것이 의미하는 바는 세마포어를 사용하는 프로그램이 Mutex를 사용하는 프로그램과 비교할 때 더 높은 메모리 풋 프린트를 갖는다는 것입니다.
  • 사용 관점에서 Mutex는 세마포어와 비교할 때 더 단순한 의미를 가지고 있습니다.

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

실제적인 차이점은 (주변 시스템 서비스 측면에서) 뮤텍스의 구현이보다 가벼운 동기화 메커니즘을 목표로한다는 것입니다. 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.

보호 된 코드 ( 중요 섹션 이라고 함) 실행을 마쳤을 때 뮤텍스 값을 0으로 설정하거나 '지우기'를 의미합니다. 여러 작업이 뮤텍스를 얻으려고 시도하는 경우 뮤텍스가 해제 된 후 예약되는 다음 작업이 리소스에 액세스 할 수 있습니다. 일반적으로 공유 데이터 구조를 업데이트하기 위해 매우 짧은 시간 동안 만 독점 액세스가 필요한 동기화 된 리소스를 제어하기 위해 뮤텍스를 사용합니다.

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

바이너리 세마포어의 경우 둘 사이의 주요 실질적인 차이점은 실제 데이터 구조를 둘러싼 시스템 서비스의 특성입니다.

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


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


뮤텍스 : T1이 접근하고자하는 임계 섹션 스레드가 있다고 가정하면 아래 단계를 따릅니다. T1 :

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

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

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

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


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

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

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


분명히 뮤텍스를 사용하여 동시에 다른 스레드에서 액세스하는 한 스레드의 데이터를 잠급니다. 방금 호출 lock()했으며 데이터에 액세스하는 중이라고 가정합니다 . 즉, 다른 스레드 (또는 동일한 스레드 코드의 다른 인스턴스)가 동일한 뮤텍스에 의해 잠긴 동일한 데이터에 액세스 할 것으로 기대하지 않습니다. 즉, 다른 스레드 인스턴스에서 실행되는 동일한 스레드 코드가 잠금에 도달하면lock()거기에서 제어 흐름을 차단해야합니다. 이것은 동일한 데이터에 액세스하고 동일한 뮤텍스에 의해 잠긴 다른 스레드 코드를 사용하는 스레드에 적용됩니다. 이 경우 여전히 데이터에 액세스하는 중이며 뮤텍스 잠금 해제에 도달하는 데 15 초가 더 걸릴 수 있습니다 (뮤텍스 잠금에서 차단 된 다른 스레드가 차단 해제되고 컨트롤이 데이터에 액세스). 어떤 대가를 치르더라도 다른 스레드가 동일한 뮤텍스를 잠금 해제하도록 허용하고, 차례로 뮤텍스 잠금에서 이미 대기 (차단)중인 스레드가 데이터를 차단 해제하고 액세스하도록 허용합니까? 내가 여기서 무슨 말을하는지 이해하길 바래? 에 따라 보편적 정의에 동의했습니다!,

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

따라서 뮤텍스 대신 이진 세마포어를 사용하는 데 매우 특별한 경우 잠금 및 잠금 해제를 "범위 지정"하는 데 매우주의해야합니다. 즉, 모든 잠금에 적용되는 모든 제어 흐름은 잠금 해제 호출에 도달해야하며 "첫 번째 잠금 해제"가 있어서는 안되며 항상 "첫 번째 잠금"이어야합니다.


Mutex는 "Locking Mechanisms"에 사용됩니다. 한 번에 하나의 프로세스가 공유 리소스를 사용할 수 있습니다.

이므로

Semaphores는 "I am done, now can continue"와 같은 "Signaling Mechanisms"에 사용됩니다.


신화:

몇 가지 기사에서는 "바이너리 세마포어와 뮤텍스가 동일하다"또는 "값이 1 인 세마포어가 뮤텍스"라고하지만 기본적인 차이점은 뮤텍스를 획득 한 스레드에 의해서만 해제 될 수 있으며 다른 스레드에서 세마포어를 신호 할 수 있다는 것입니다.

키 포인트:

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

• 뮤텍스는 재귀 뮤텍스 인 경우에만 두 번 이상 잠글 수 있습니다. 여기서 뮤텍스의 잠금과 잠금 해제가 동일해야합니다.

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

• 바이너리 세마포어와 뮤텍스는 비슷하지만 같지는 않습니다.

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

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


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

세마포어 자원의 공유 풀에 대한 액세스를 제어합니다. 풀의 리소스 중 하나를 사용할 수있을 때까지 Wait ()에 작업을 제공 하고 풀에 다시 제공되면 Signal () 에 작업을 제공합니다.

Semaphore가 보호하는 리소스 수가 1보다 클 때 Counting Semaphore 라고합니다 . 하나의 리소스를 제어 할 때 Boolean Semaphore 라고합니다 . 부울 세마포어는 뮤텍스와 동일합니다.

따라서 Semaphore는 Mutex보다 더 높은 수준의 추상화입니다. Mutex는 Semaphore를 사용하여 구현할 수 있지만 그 반대는 아닙니다.


뮤텍스는 임계 영역을 차단하는 데 사용되지만 세마포어는 계산에 사용됩니다.


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

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

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

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


바이너리 세마포어와 뮤텍스의 차이점 : 소유권 : 세마포어는 현재가 아닌 소유자로부터도 신호 (게시) 될 수 있습니다. 즉, 소유자는 아니지만 다른 스레드에서 게시 할 수 있습니다.

Semaphore는 처리중인 공용 속성이며 소유자가 아닌 스레드에 의해 간단히 게시 될 수 있습니다. 이 차이를 굵은 글씨로 표시하십시오.


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

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

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


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


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


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

가져 가지 않고 세마포어를 주려고하면 통과합니다. 그러나 뮤텍스를 사용하지 않고 제공하려고하면 실패합니다. 나는 이것을 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;
}

The very fact that semaphore lets you signal "it is done using a resource", even though it never owned the resource, makes me think there is a very loose coupling between owning and signaling in the case of semaphores.


While a binary semaphore may be used as a mutex, a mutex is a more specific use-case, in that only the process that locked the mutex is supposed to unlock it. This ownership constraint makes it possible to provide protection against:

  • Accidental release
  • Recursive Deadlock
  • Task Death Deadlock

These constraints are not always present because they degrade the speed. During the development of your code, you can enable these checks temporarily.

e.g. you can enable Error check attribute in your mutex. Error checking mutexes return EDEADLK if you try to lock the same one twice and EPERM if you unlock a mutex that isn't yours.

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);

Once initialised we can place these checks in our code like this:

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

Mutex is used to protect the sensitive code and data, semaphore is used to synchronization.You also can have practical use with protect the sensitive code, but there might be a risk that release the protection by the other thread by operation V.So The main difference between bi-semaphore and mutex is the ownership.For instance by toilet , Mutex is like that one can enter the toilet and lock the door, no one else can enter until the man get out, bi-semaphore is like that one can enter the toilet and lock the door, but someone else could enter by asking the administrator to open the door, it's ridiculous.


Mutex

Mutexes are typically used to serialise access to a section of re-entrant code that cannot be executed concurrently by more than one thread. A mutex object only allows one thread into a controlled section, forcing other threads which attempt to gain access to that section to wait until the first thread has exited from that section.Proper use of a mutex is to protect a shared resource can have a dangerous unintended side effect. Any two RTOS tasks that operate at different priorities and coordinate via a mutex, create the opportunity for priority inversion. Mutex works in user space.

Semaphore

Semaphore is a signalling mechanism. Semaphore restricts the number of simultaneous users of a shared resource up to a maximum number. Threads can request access to the resource (decrementing the semaphore) and can signal that they have finished using the resource (incrementing the semaphore). It allows number of thread to access shared resources.The correct use of a semaphore is for signaling from one task to another.semaphores can also be used to signal from an interrupt service routine (ISR) to a task. Signaling a semaphore is a non-blocking RTOS behavior and thus ISR safe. Because this technique eliminates the error-prone need to disable interrupts at the task level.This works in kernel space.


The answer may depend on the target OS. For example, at least one RTOS implementation I'm familiar with will allow multiple sequential "get" operations against a single OS mutex, so long as they're all from within the same thread context. The multiple gets must be replaced by an equal number of puts before another thread will be allowed to get the mutex. This differs from binary semaphores, for which only a single get is allowed at a time, regardless of thread contexts.

The idea behind this type of mutex is that you protect an object by only allowing a single context to modify the data at a time. Even if the thread gets the mutex and then calls a function that further modifies the object (and gets/puts the protector mutex around its own operations), the operations should still be safe because they're all happening under a single thread.

{
    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.
}

Of course, when using this feature, you must be certain that all accesses within a single thread really are safe!

I'm not sure how common this approach is, or whether it applies outside of the systems with which I'm familiar. For an example of this kind of mutex, see the ThreadX RTOS.


Mutexes have ownership, unlike semaphores. Although any thread, within the scope of a mutex, can get an unlocked mutex and lock access to the same critical section of code,only the thread that locked a mutex should unlock it.


As many folks here have mentioned, a mutex is used to protect a critical piece of code (AKA critical section.) You will acquire the mutex (lock), enter critical section, and release mutex (unlock) all in the same thread.

While using a semaphore, you can make a thread wait on a semaphore (say thread A), until another thread (say thread B)completes whatever task, and then sets the Semaphore for thread A to stop the wait, and continue its task.


Mutex and binary semaphore are both of the same usage, but in reality, they are different.

In case of mutex, only the thread which have locked it can unlock it. If any other thread comes to lock it, it will wait.

In case of semaphone, that's not the case. Semaphore is not tied up with a particular thread ID.


"binary semaphore" is a programming language circumvent to use a «semaphore» like «mutex». Apparently there are two very big differences:

  1. The way you call each one of them.

  2. The maximum length of the "identifier".

참고URL : https://stackoverflow.com/questions/62814/difference-between-binary-semaphore-and-mutex

반응형