development

조건부 변수 대 세마포

big-blog 2020. 9. 4. 07:53
반응형

조건부 변수 대 세마포


언제 세마포어를 사용해야하고 언제 조건 변수 (CondVar)를 사용해야합니까?


잠금은 상호 배제에 사용됩니다. 코드 조각이 원 자성인지 확인하려면 그 주위에 잠금 장치를 두십시오. 이론적으로 이진 세마포어를 사용하여이 작업을 수행 할 수 있지만 이는 특별한 경우입니다.

세마포어 및 조건 변수는 잠금에 의해 제공되는 상호 배제 위에 구축되며 공유 리소스에 대한 동기화 된 액세스를 제공하는 데 사용됩니다. 유사한 목적으로 사용할 수 있습니다.

조건 변수는 일반적으로 리소스를 사용할 수있을 때까지 기다리는 동안 바쁜 대기 (조건을 확인하는 동안 반복해서 반복)를 방지하는 데 사용됩니다. 예를 들어 큐가 비워 질 때까지 계속할 수없는 스레드 (또는 여러 스레드)가있는 경우 바쁜 대기 방식은 다음과 같은 작업을 수행하는 것입니다.

//pseudocode
while(!queue.empty())
{
   sleep(1);
}

문제는이 스레드가 조건을 반복적으로 확인하도록하여 프로세서 시간을 낭비하고 있다는 것입니다. 대신 자원을 사용할 수 있음을 스레드에 알리기 위해 신호를 보낼 수있는 동기화 변수가없는 이유는 무엇입니까?

//pseudocode
syncVar.lock.acquire();

while(!queue.empty())
{
   syncVar.wait();
}

//do stuff with queue

syncVar.lock.release();

아마도 대기열에서 물건을 꺼내는 다른 스레드가있을 것입니다. 큐가 비어 있으면 대기 syncVar.signal()중인 임의의 스레드를 깨우기 위해 호출 할 수 있습니다 syncVar.wait()(또는 일반적으로 대기중인 모든 스레드를 깨우는 signalAll()또는 broadcast()메서드 도 있습니다 ).

일반적으로 단일 특정 조건 (예 : 대기열이 비어있는 경우)에서 대기중인 스레드가 하나 이상있을 때 이와 같은 동기화 변수를 사용합니다.

세마포어도 비슷하게 사용할 수 있지만 몇 가지 정수를 기반으로 사용할 수 있고 사용할 수없는 공유 리소스가있을 때 더 잘 사용된다고 생각합니다. 세마포는 생산자가 리소스를 할당하고 소비자가이를 소비하는 생산자 / 소비자 상황에 적합합니다.

탄산 음료 자판기가 있는지 생각해보십시오. 탄산 음료 머신은 하나 뿐이며 공유 리소스입니다. 기계 재고를 유지하는 공급 업체 (생산자) 인 스레드 하나와 기계에서 탄산 음료를 꺼내고 자하는 구매자 (소비자) 인 스레드 N 개가 있습니다. 기계의 탄산 음료 수는 세마포어를 구동하는 정수 값입니다.

소다 기계에 오는 모든 구매자 (소비자) 스레드는 세마포어 down()메서드를 호출하여 소다를 가져 옵니다 . 이렇게하면 기계에서 탄산 음료를 가져와 사용 가능한 탄산 음료의 수를 1만큼 줄입니다. 사용 가능한 탄산 음료가 있으면 코드가 down()문제없이 문을 지나 계속 실행 됩니다. 탄산 음료를 사용할 수없는 경우 스레드는 여기에서 잠자기 상태가되어 탄산 음료가 다시 사용 가능해질 때 알림을받습니다 (머신에 탄산 음료가 더있을 때).

공급 업체 (생산자) 스레드는 본질적으로 탄산 음료 기계가 비어 있기를 기다리고 있습니다. 공급 업체는 기계에서 마지막 탄산 음료를 가져 오면 알림을받습니다 (그리고 한 명 이상의 소비자가 탄산 음료를 꺼내기를 기다리고있을 가능성이 있음). 공급 업체는 세마포어 up()방법으로 소다 기계를 재입고하고 , 사용 가능한 소다 수는 매번 증가하므로 대기중인 소비자 스레드는 더 많은 소다를 사용할 수 있다는 알림을받습니다.

동기화 변수 wait()signal()메서드 는 세마포어 down()up()작업 내에 숨겨지는 경향이 있습니다 .

확실히 두 선택 사이에 겹치는 부분이 있습니다. 세마포어 또는 조건 변수 (또는 조건 변수 세트)가 모두 사용자의 목적에 부합 할 수있는 시나리오가 많이 있습니다. 세마포어와 조건 변수는 모두 상호 배제를 유지하는 데 사용하는 잠금 개체와 연결되어 있지만 스레드 실행 동기화를 위해 잠금 위에 추가 기능을 제공합니다. 귀하의 상황에 가장 적합한 것이 무엇인지 파악하는 것은 대부분 귀하에게 달려 있습니다.

이것이 반드시 가장 기술적 인 설명은 아니지만 그것이 내 머릿속에서 이해되는 방식입니다.


내부에 무엇이 있는지 밝혀 봅시다.

Conditional variable is essentially a wait-queue, that supports blocking-wait and wakeup operations, i.e. you can put a thread into the wait-queue and set its state to BLOCK, and get a thread out from it and set its state to READY.

Note that to use a conditional variable, two other elements are needed:

  • a condition (typically implemented by checking a flag or a counter)
  • a mutex that protects the condition

The protocol then becomes,

  1. acquire mutex
  2. check condition
  3. block and release mutex if condition is true, else release mutex

Semaphore is essentially a counter + a mutex + a wait queue. And it can be used as it is without external dependencies. You can use it either as a mutex or as a conditional variable.

Therefore, semaphore can be treated as a more sophisticated structure than conditional variable, while the latter is more lightweight and flexible.


Semaphores can be used to implement exclusive access to variables, however they are meant to be used for synchronization. Mutexes, on the other hand, have a semantics which is strictly related to mutual exclusion: only the process which locked the resource is allowed to unlock it.

Unfortunately you cannot implement synchronization with mutexes, that's why we have condition variables. Also notice that with condition variables you can unlock all the waiting threads in the same instant by using the broadcast unlocking. This cannot be done with semaphores.


semaphore and condition variables are very similar and are used mostly for the same purposes. However, there are minor differences that could make one preferable. For example, to implement barrier synchronization you would not be able to use a semaphore.But a condition variable is ideal.

Barrier synchronization is when you want all of your threads to wait until everyone has arrived at a certain part in the thread function. this can be implemented by having a static variable which is initially the value of total threads decremented by each thread when it reaches that barrier. this would mean we want each thread to sleep until the last one arrives.A semaphore would do the exact opposite! with a semaphore, each thread would keep running and the last thread (which will set semaphore value to 0) will go to sleep.

a condition variable on the other hand, is ideal. when each thread gets to the barrier we check if our static counter is zero. if not, we set the thread to sleep with the condition variable wait function. when the last thread arrives at the barrier, the counter value will be decremented to zero and this last thread will call the condition variable signal function which will wake up all the other threads!


I file condition variables under monitor synchronization. I've generally seen semaphores and monitors as two different synchronization styles. There are differences between the two in terms of how much state data is inherently kept and how you want to model code - but there really isn't any problem that can be solved by one but not the other.

I tend to code towards monitor form; in most languages I work in that comes down to mutexes, condition variables, and some backing state variables. But semaphores would do the job too.

참고URL : https://stackoverflow.com/questions/3513045/conditional-variable-vs-semaphore

반응형