수색…


소개

조건부 변수는 스레드가 다른 스레드에서 발생하는 것을 기다리고 싶을 때 유용합니다. 예를 들어, 하나 이상의 생성 쓰레드와 하나의 소비 쓰레드를 가진 생산자 / 소비자 시나리오에서, 조건 변수는 새로운 쓰레드가 사용 가능한 쓰레드를 알리기 위해 사용될 수있다.

비고

일반 과정

조건부 변수 (생산자 / 소비자 예제의 queueCond)에 대한 대기는 항상 mutex (생산자 / 소비자 예제의 queueMutex)와 결합되며 항상 "정상적인"상태 변수 (queue.empty )를 생산자 / 소비자 예제에서 사용). 올바르게 사용하면 소비자에게 새로운 데이터가 누락되지 않습니다.

일반적으로 프로세스는 다음과 같아야합니다.

  • 신호 스레드의 경우 :
    1. 뮤텍스 잠금
    2. 모든 데이터 및 상태 변수 업데이트
    3. 조건 변수 신호
    4. 뮤텍스 잠금 해제
  • 대기중인 스레드의 경우 :
    1. 뮤텍스 잠금
    2. 상태 변수에 while 루프를 수행하고 데이터가 준비되지 않은 한 반복합니다.
    3. while 루프에서는 pthread_cond_wait() 조건 변수를 기다린다.
    4. while 루프가 종료되면 새로운 데이터가 준비되어 있고 뮤텍스가 잠겨 있는지 확인합니다
    5. 데이터로 무언가를하십시오
    6. 뮤텍스의 잠금을 해제하고 반복하십시오.

시그널링과 대기 스레드가 언제 스케줄링 되든 관계없이이 스킴을 사용하면 대기중인 쓰레드는 결코 데이터를 놓칠 수 없다. (유효한 데이터가 준비되면 영원히 기다리지 않아도된다.) 이는 신호 스레드의 단계를 수동으로 실행하고 대기중인 스레드의 각 단계에 대해 뮤텍스, 상태 및 상태 변수의 상태를 기록하여 실현할 수 있습니다.

pthread_cond_wait 와 뮤텍스

위의 프로세스를 용이하게하려면 mutex가 잠긴 상태로 pthread_cond_wait() 를 호출해야합니다. 호출되면, pthread_cond_wait() 는 쓰레드를 잠자기 상태로 만들기 전에 뮤텍스의 잠금을 해제하고, 어떤 이유에서든 리턴하기 바로 전에 뮤텍스를 다시 잠급니다. 이것은 또한 다른 스레드가 현재 뮤텍스를 잠근 경우 pthread_cond_wait() 는 뮤텍스가 잠금 해제 될 때까지 대기하고 대기중인 스레드가 실제로 뮤텍스를 획득 할 때까지 잠글 것을 시도하는 다른 스레드와 함께 스레드와 경쟁 할 것이라는 것을 의미합니다. 동시에 뮤텍스.

허위 모닝콜

또한 상태 변수를 기다리는 while 루프가 간단한 if 문으로 대체 될 수있는 것처럼 보일 수 있습니다. 그러나 Posix 표준은 pthread_cond_wait() 가 실제로 신호를받지 않고 대기 중에 소위 "가짜"웨이크 업을 수행 할 수 있으므로 while 루프가 필요합니다. 따라서 코드는 pthread_cond_wait() 가 실제로 시그널링 되었기 때문에 반환되었는지 또는 이러한 허위 웨이크 업 중 하나 때문에 상태 변수를 다시 검사해야합니다.

생산자 / 소비자 예제

pthread_mutex_t queueMutex;
pthread_cond_t queueCond;
Queue queue;

void Initialize() {
    //Initialize the mutex and the condition variable
    pthread_mutex_init(&queueMutex, NULL);
    pthread_cond_init(&queueCond, NULL);
}

void Producer() {
    //First we get some new data
    Data *newData = MakeNewData();

    //Lock the queue mutex to make sure that adding data to the queue happens correctly
    pthread_mutex_lock(&queueMutex);

    //Push new data to the queue
    queue.push(newData);

    //Signal the condition variable that new data is available in the queue
    pthread_cond_signal(&queueCond);

    //Done, unlock the mutex
    pthread_mutex_unlock(&queueMutex);
}


void Consumer() {

    //Run the consumer loop
    while(1) {

        //Start by locking the queue mutex
        pthread_mutex_lock(&queueMutex);

        //As long as the queue is empty,
        while(queue.empty()) {
            // - wait for the condition variable to be signalled
            //Note: This call unlocks the mutex when called and
            //relocks it before returning!
            pthread_cond_wait(&queueCond, &queueMutex);
        }

        //As we returned from the call, there must be new data in the queue - get it,
        Data *newData = queue.front();
        // - and remove it from the queue
        queue.pop();

        //Now unlock the mutex
        pthread_mutex_unlock(&queueMutex);
        
        // - and process the new data
        ProcessData(newData);
    }
}


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow