pthreads의 조건 변수 함수에 뮤텍스가 필요한 이유는 무엇입니까?


182

나는 계속 읽고있다 pthread.h; 조건 변수 관련 함수 (예 pthread_cond_wait(3):)에는 인수로 뮤텍스가 필요합니다. 왜? 지금까지 내가 말할 수있는, 내가 뮤텍스를 생성 할거야 단지 그 인수로 사용할 수 있나요? 그 뮤텍스는 무엇을해야합니까?

답변:


194

조건 변수가 (또는 원래) 구현 된 방식 일뿐입니다.

뮤텍스는 조건 변수 자체 를 보호 하는 데 사용 됩니다 . 그래서 기다리기 전에 잠 가야하는 이유입니다.

대기는 뮤텍스를 "원자 적으로"잠금 해제하여 다른 사람들이 조건 신호에 액세스 할 수있게합니다 (신호 발생). 그런 다음 조건 변수에 신호를 보내거나 브로드 캐스트하면 대기 목록의 스레드 중 하나 이상이 깨어나고 해당 스레드에 대해 뮤텍스가 다시 마술처럼 고정됩니다.

일반적으로 조건 변수와 함께 다음 작업이 작동 방식을 보여줍니다. 다음 예제는 조건 변수에 대한 신호를 통해 작업이 제공되는 작업자 스레드입니다.

thread:
    initialise.
    lock mutex.
    while thread not told to stop working:
        wait on condvar using mutex.
        if work is available to be done:
            do the work.
    unlock mutex.
    clean up.
    exit thread.

대기가 리턴 될 때 사용 가능한 것이 있으면이 루프 내에서 작업이 수행됩니다. 스레드가 작업을 중지하도록 플래그가 지정되면 (보통 다른 스레드가 종료 조건을 설정 한 후 조건 변수를 시작하여 스레드를 깨우기 위해) 루프가 종료되고 뮤텍스가 잠금 해제되고이 스레드가 종료됩니다.

위의 코드는 작업이 완료되는 동안 뮤텍스가 잠긴 상태에서 단일 소비자 모델입니다. 멀티 소비자의 변화를 들어, 당신은 같이 사용할 수 있습니다 :

thread:
    initialise.
    lock mutex.
    while thread not told to stop working:
        wait on condvar using mutex.
        if work is available to be done:
            copy work to thread local storage.
            unlock mutex.
            do the work.
            lock mutex.
    unlock mutex.
    clean up.
    exit thread.

이것은 다른 소비자가 일을하는 동안 일을받을 수있게합니다.

조건 변수는 어떤 상황을 폴링해야하는 부담을 덜어 주지만 대신 어떤 상황이 발생할 때 다른 스레드가 사용자에게 알려줄 수 있습니다. 다른 스레드는 다음과 같이 스레드가 작동 함을 알 수 있습니다.

lock mutex.
flag work as available.
signal condition variable.
unlock mutex.

종종 잘못된 pthread_cond_wait모닝콜 이라고 잘못 부르는 것의 대다수는 일반적으로 여러 스레드가 호출 (브로드 캐스트) 내에서 신호를 보냈기 때문에 뮤텍스와 함께 돌아와서 작업을 수행 한 다음 다시 대기하기 때문입니다.

그런 다음 수행 할 작업이 없을 때 두 번째 신호 스레드가 나올 수 있습니다. 따라서 작업을 수행해야 함을 나타내는 추가 변수가 있어야했습니다 (이것은 본질적으로 condvar / mutex 쌍으로 뮤텍스로 보호되었습니다-그러나 다른 스레드는 뮤텍스를 변경하기 전에 뮤텍스를 잠그는 데 필요했습니다).

그것은 이었다 쓰레드가 다른 프로세스에 의해 쫓겨되지 않고 상태 대기에서 반환하는 pthreads의 작업을 모두 개발 / 코드의 서비스와 사용자로 내 여러 해에, (이 진짜 가짜 웨이크 업입니다)하지만, 기술적으로 가능 그들 중 한 번도이 중 하나를받지 못했습니다. 어쩌면 HP가 적절한 구현을했기 때문일 수도 있습니다 :-)

어쨌든, 잘못된 케이스를 처리 한 동일한 코드도 작업 가능한 플래그가 설정되지 않았기 때문에 진짜 가짜 웨이크 업도 처리했습니다.


3
while 루프 안에 있으면 안됩니다. while 루프가 상태를 확인하기를 원한다면, 가짜 웨이크가 발생하면 '무언가'를 수행 할 수도 있습니다.
nos

1
아니오, 오류 처리는 이보다 두 번째입니다. pthreads를 사용하면 명백한 이유없이 (가짜 모닝콜) 오류없이 깨어날 수 있습니다. 따라서 깨어 난 후 '일부 상태'를 다시 확인해야합니다.
nos

1
잘 모르겠습니다. 나는 nos 와 같은 반응을 보였습니다 . 왜 루프 do something안에 while있습니까?
ELLIOTTCABLE

1
아마도 나는 그것을 충분히 명확하게하지 않을 것입니다. 루프입니다 하지 당신이 그것을 할 수 있도록 준비 작업에 대 한 대기. 루프는 주요 "무한"작업 루프입니다. cond_wait에서 돌아와서 작업 플래그가 설정되면 작업을 수행 한 다음 다시 반복합니다. 스레드가 뮤텍스를 해제하고 종료 될 가능성이있는 시점에서 스레드가 작업을 중지하도록하려는 경우 "일부 조건"은 거짓입니다.
paxdiablo

7
@stefaanv "뮤텍스는 여전히 조건 변수를 보호하기 위해, 그것을 보호하는 다른 방법은 없습니다": 뮤텍스는 조건 변수를 보호 하지 않습니다 ; 그것은 술어 데이터 를 보호하는 것이지만, 나는 당신이 그 진술을 따르는 당신의 의견을 읽음으로써 그것을 알고 있다고 생각합니다. 조건 변수를 합법적으로 신호 화하고 구현에 의해 완전히 지원되며 술어를 래핑하는 뮤텍스의 잠금 해제 사실을 알릴 수 있으며 실제로는 경우에 따라 경합을 완화 시킬 수 있습니다.
WhozCraig

59

조건 만 신호 할 수있는 경우 조건 변수는 상당히 제한적입니다. 일반적으로 신호가 발생한 조건과 관련된 일부 데이터를 처리해야합니다. 경쟁 조건을 도입하지 않고 지나치게 복잡해 지려면 신호 처리 / 웨이크 업을 원자 적으로 수행해야합니다.

pthreads는 기술적 인 이유로 가짜 웨이크 업을 제공 할 수도 있습니다 . 즉, 술어를 확인해야하므로 조건이 실제로 신호되었는지 확인하고 가짜 웨이크 업과 구별 할 수 있습니다. 대기 상태와 관련하여 이러한 조건을 확인하려면 보호해야합니다. 따라서 조건 변수는 해당 조건을 보호하는 뮤텍스를 잠 그거나 잠금 해제하는 동안 원자 적으로 대기 / 깨우는 방법이 필요합니다.

일부 데이터가 생성되었다는 알림을받는 간단한 예를 고려하십시오. 다른 스레드가 원하는 데이터를 만들고 해당 데이터에 대한 포인터를 설정했을 수 있습니다.

'some_data'포인터를 통해 일부 소비자 데이터를 다른 소비자 스레드에 제공하는 생산자 스레드를 상상해보십시오.

while(1) {
    pthread_cond_wait(&cond); //imagine cond_wait did not have a mutex
    char *data = some_data;
    some_data = NULL;
    handle(data);
}

당신은 자연스럽게 많은 경쟁 조건 some_data = new_data을 갖게 될 것입니다. 만약 당신이 깨어 난 직후에 다른 스레드가 그랬다면 어떻게 합니까?data = some_data

이 경우를 지키기 위해 자신의 뮤텍스를 실제로 만들 수는 없습니다.

while(1) {

    pthread_cond_wait(&cond); //imagine cond_wait did not have a mutex
    pthread_mutex_lock(&mutex);
    char *data = some_data;
    some_data = NULL;
    pthread_mutex_unlock(&mutex);
    handle(data);
}

작동하지 않지만 뮤텍스를 깨우고 잡는 사이에 여전히 경쟁 조건이 있습니다. pthread_cond_wait 앞에 뮤텍스를 배치해도 도움이되지 않습니다. 대기하는 동안 뮤텍스를 잡아야합니다. 즉, 생산자는 절대 뮤텍스를 잡을 수 없습니다. (이 경우 생산자에게 완료되었음을 알리는 두 번째 조건 변수를 작성할 수 있습니다. some_data특히 생산자 / 소비자가 많은 경우 복잡해집니다.)

따라서 조건에서 대기 / 깨어날 때 뮤텍스를 원자 적으로 해제 / 잡을 수있는 방법이 필요합니다. 이것이 pthread 조건 변수가하는 일이며, 여기 당신이하는 일이 있습니다 :

while(1) {
    pthread_mutex_lock(&mutex);
    while(some_data == NULL) { // predicate to acccount for spurious wakeups,would also 
                               // make it robust if there were several consumers
       pthread_cond_wait(&cond,&mutex); //atomically lock/unlock mutex
    }

    char *data = some_data;
    some_data = NULL;
    pthread_mutex_unlock(&mutex);
    handle(data);
}

(생산자는 자연스럽게 동일한 예방 조치를 취해야하며 항상 같은 뮤텍스로 'some_data'를 지키고 some_data가 현재! = NULL 인 경우 some_data를 덮어 쓰지 않아야합니다)


while (some_data != NULL)조건 변수를 한 번 이상 기다리도록 do-while 루프가 아니어야합니까 ?
Maygarden 판사

3
아니요. 실제로 기다리는 것은 'some_data'가 null이 아닌 것입니다. "처음"이 null이 아닌 경우, 뮤텍스를 잡고 있으므로 안전하게 데이터를 사용할 수 있습니다. 만약 당신이 do / while 루프를 가지고 있다면 누군가 누군가 당신이 기다리기 전에 조건 변수에 신호를 보내면 알림을 놓치게 될 것입니다 (win32에서 누군가가 그들을 기다릴 때까지 신호를 보내는 이벤트와 같은 것은 아닙니다)
nos

4
나는이 질문에 우연히 넘어 갔고 솔직히이 대답은 명확한 결함이있는 paxdiablo의 대답보다 훨씬 적은 점수를 가지고 있다는 것을 발견하는 것이 이상합니다 (원 자성이 여전히 필요하며 뮤텍스는 조건을 처리하는 데만 필요합니다. 취급 또는 통지 용이 아님). 나는 그것이 stackoverflow가 작동하는 방식 일 뿐이라고 생각합니다.
stefaanv

@stefaanv, 결함에 대해 자세하게 설명하고 싶다면 내 답변에 대한 의견으로 몇 달 후 :-)가 아닌 적시에 볼 수 있도록 수정 해 드리겠습니다. 당신의 짧은 문구는 실제로 당신이 말하려는 것을 해결하기에 충분한 세부 사항을 제공하지 않습니다.
paxdiablo

1
@nos,하지 말아야 while(some_data != NULL)while(some_data == NULL)?
Eric Z

30

POSIX 조건 변수는 상태 비 저장입니다. 따라서 국가를 유지하는 것은 귀하의 책임입니다. 대기하는 스레드와 다른 스레드에게 대기를 중지하도록 지시하는 스레드가 상태에 액세스하므로 뮤텍스에 의해 보호되어야합니다. 뮤텍스없이 조건 변수를 사용할 수 있다고 생각하면 조건 변수가 상태가 없다는 것을 파악하지 못했습니다.

조건 변수는 조건 주위에 구축됩니다. 조건 변수를 기다리는 스레드가 일부 조건을 기다리고 있습니다. 조건 변수를 신호하는 스레드가 해당 조건을 변경합니다. 예를 들어, 스레드가 일부 데이터가 도착하기를 기다리는 중일 수 있습니다. 다른 스레드는 데이터가 도착했음을 알 수 있습니다. "데이터가 도착했습니다"가 조건입니다.

다음은 단순화 된 조건 변수의 일반적인 사용법입니다.

while(1)
{
    pthread_mutex_lock(&work_mutex);

    while (work_queue_empty())       // wait for work
       pthread_cond_wait(&work_cv, &work_mutex);

    work = get_work_from_queue();    // get work

    pthread_mutex_unlock(&work_mutex);

    do_work(work);                   // do that work
}

스레드가 작업을 기다리는 방법을 참조하십시오. 작품은 뮤텍스에 의해 보호됩니다. 대기는 뮤텍스를 해제하여 다른 스레드가이 스레드에 약간의 작업을 제공 할 수 있도록합니다. 신호를받는 방법은 다음과 같습니다.

void AssignWork(WorkItem work)
{
    pthread_mutex_lock(&work_mutex);

    add_work_to_queue(work);           // put work item on queue

    pthread_cond_signal(&work_cv);     // wake worker thread

    pthread_mutex_unlock(&work_mutex);
}

공지 사항 당신은 필요한 작업 큐를 보호하기 위해 뮤텍스를. 조건 변수 자체에는 작동 여부가 없습니다. 즉, 조건 변수 조건 과 연결 되어야 하며 해당 조건은 코드에서 유지 관리해야하며 스레드간에 공유되므로 뮤텍스에 의해 보호되어야합니다.


1
또는 더 간결하게 말하면 조건 조건의 전체 지점은 원자 적 "잠금 해제 및 대기"작업을 제공하는 것입니다. 뮤텍스가 없으면 잠금 해제 할 항목이 없습니다.
David Schwartz

무국적 의 의미를 설명해 주시겠습니까 ?
snr

@snr 상태가 없습니다. "잠금"또는 "신호"또는 "신호 없음"이 아닙니다. 따라서 조건 변수와 관련된 상태를 추적하는 것은 귀하의 책임입니다. 예를 들어 조건 변수가 대기열에 비어 있지 않은 시점을 스레드에 알리면 하나의 스레드가 대기열을 비어 있지 않은 상태로 만들고 다른 스레드가 대기열이 비어 있지 않은 시점을 알아야하는 경우 여야합니다. 공유 상태이므로 뮤텍스로 보호해야합니다. 뮤텍스에 의해 보호되는 공유 상태와 관련하여 조건 변수를 웨이크 업 메커니즘으로 사용할 수 있습니다.
David Schwartz

16

모든 조건 변수 함수에 뮤텍스가 필요한 것은 아닙니다. 대기 작업 만 가능합니다. 신호 및 방송 작업에는 뮤텍스가 필요하지 않습니다. 조건 변수는 특정 뮤텍스와 영구적으로 연관되지 않습니다. 외부 뮤텍스는 조건 변수를 보호하지 않습니다. 조건 변수에 대기중인 스레드 큐와 같은 내부 상태가있는 경우 조건 변수 내부의 잠금으로 보호해야합니다.

대기 작업은 다음과 같은 이유로 조건 변수와 뮤텍스를 결합합니다.

  • 스레드가 뮤텍스를 잠그고 공유 변수에 대한 일부 표현식을 평가 한 후 거짓임을 발견하여 대기해야합니다.
  • 스레드는 원자 적으로 뮤텍스 소유에서 조건 대기로 이동 해야합니다 .

이러한 이유로 대기 작업은 뮤텍스와 조건을 모두 인수로 사용하여 뮤텍스 소유에서 대기로 스레드의 원자 전송을 관리 할 수 ​​있으므로 스레드가 웨이크 업 경쟁 조건에 희생되지 않습니다 .

스레드가 뮤텍스를 포기한 다음 상태 비 저장 동기화 객체를 대기하지만 원자 적이 지 않은 방식으로 대기하는 경우 웨이크 업 경쟁 조건이 발생합니다. 스레드에 더 이상 잠금이없는 시간 창이 있습니다. 아직 객체를 기다리지 않았습니다. 이 창에서 다른 스레드가 들어 와서 대기 상태를 true로 만들고 상태 비 저장 동기화 신호를 보낸 다음 사라질 수 있습니다. 상태 비 저장 개체는 신호가 있다는 것을 기억하지 못합니다 (상태 비 저장). 따라서 원래 스레드는 상태 비 저장 동기화 개체에서 절전 모드로 전환되고 필요한 조건이 이미 충족 되었더라도 깨어나지 않습니다.

조건 변수 대기 함수는 호출 스레드가 뮤텍스를 포기하기 전에 웨이크 업을 안정적으로 포착하도록 등록되어 웨이크 업 손실을 피합니다. 조건 변수 대기 함수가 뮤텍스를 인수로 사용하지 않으면 불가능합니다.


브로드 캐스트 조작이 뮤텍스를 획득 할 필요가 없다는 참조를 제공 할 수 있습니까? MSVC에서는 브로드 캐스트가 무시됩니다.
xvan

@xvan POSIX pthread_cond_broadcastpthread_cond_signal연산 (이 SO 질문에 관한)은 뮤텍스를 인수로 취하지도 않습니다. 조건 만. POSIX 사양은 여기에 있습니다 . 뮤텍스는 대기중인 스레드가 깨어날 때 발생하는 내용과 관련하여 언급됩니다.
Kaz

무국적 의 의미를 설명해 주시겠습니까 ?
snr

1
@snr 상태 비 저장 동기화 개체는 신호와 관련된 상태를 기억하지 않습니다. 신호를 받으면 지금 기다리고있는 것이 있으면 깨어납니다. 그렇지 않으면 깨어납니다. 조건 변수는 이와 같이 상태가 없습니다. 동기화를 안정적으로 만드는 데 필요한 상태는 응용 프로그램에서 유지 관리되며 올바르게 작성된 논리에 따라 조건 변수와 함께 사용되는 뮤텍스에 의해 보호됩니다.
Kaz

7

나는 이 페이지 만큼 간결하고 읽기 쉬운 다른 답변을 찾지 못했다 . 일반적으로 대기 코드는 다음과 같습니다.

mutex.lock()
while(!check())
    condition.wait()
mutex.unlock()

wait()뮤텍스 를 감싸는 데는 세 가지 이유가 있습니다 .

  1. 뮤텍스가 없으면 다른 스레드가 signal()전에 할 수 있으며이 wait()깨우기가 빠질 것입니다.
  2. 일반적으로 check()다른 스레드의 수정에 의존하므로 어쨌든 상호 제외가 필요합니다.
  3. 우선 순위가 가장 높은 스레드가 먼저 진행되도록합니다 (뮤텍스의 큐를 통해 스케줄러가 다음에 누가 갈 것인지 결정할 수 있음).

세 번째 요점이 항상 우려되는 것은 아닙니다. 역사적 맥락이 기사 와이 대화에 연결되어 있습니다 .

이 메커니즘과 관련하여 가짜 웨이크 업이 종종 언급됩니다 (즉, 대기 스레드가 signal()호출 되지 않고 해제 됨 ). 그러나 이러한 이벤트는 looped에 의해 처리됩니다 check().


4

조건 변수는 피하도록 설계된 경쟁을 피할 수있는 유일한 방법이기 때문에 뮤텍스와 연관됩니다.

// incorrect usage:
// thread 1:
while (notDone) {
    pthread_mutex_lock(&mutex);
    bool ready = protectedReadyToRunVariable
    pthread_mutex_unlock(&mutex);
    if (ready) {
        doWork();
    } else {
        pthread_cond_wait(&cond1); // invalid syntax: this SHOULD have a mutex
    }
}

// signalling thread
// thread 2:
prepareToRunThread1();
pthread_mutex_lock(&mutex);
   protectedReadyToRuNVariable = true;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond1);

Now, lets look at a particularly nasty interleaving of these operations

pthread_mutex_lock(&mutex);
bool ready = protectedReadyToRunVariable;
pthread_mutex_unlock(&mutex);
                                 pthread_mutex_lock(&mutex);
                                 protectedReadyToRuNVariable = true;
                                 pthread_mutex_unlock(&mutex);
                                 pthread_cond_signal(&cond1);
if (ready) {
pthread_cond_wait(&cond1); // uh o!

이 시점에서 조건 변수를 알리는 스레드가 없으므로 protectedReadyToRunVariable이 갈 준비가 되었음에도 불구하고 thread1은 영원히 대기합니다!

조건 변수가이 주위에있는 유일한 방법은 원자 적으로 동시에 조건 변수에 대기하는 동안 시작 뮤텍스를 해제. 이것이 cond_wait 함수에 뮤텍스가 필요한 이유입니다

// correct usage:
// thread 1:
while (notDone) {
    pthread_mutex_lock(&mutex);
    bool ready = protectedReadyToRunVariable
    if (ready) {
        pthread_mutex_unlock(&mutex);
        doWork();
    } else {
        pthread_cond_wait(&mutex, &cond1);
    }
}

// signalling thread
// thread 2:
prepareToRunThread1();
pthread_mutex_lock(&mutex);
   protectedReadyToRuNVariable = true;
   pthread_cond_signal(&mutex, &cond1);
pthread_mutex_unlock(&mutex);

3

뮤텍스는 호출 할 때 잠겨 있어야합니다 pthread_cond_wait. 그것을 호출하면 원자 적으로 모두 뮤텍스를 잠금 해제 한 다음 조건을 차단합니다. 조건이 신호되면 원자 적으로 다시 잠그고 돌아갑니다.

이는 시그널링을 수행하는 스레드가 뮤텍스가 해제 될 때까지 기다렸다가 그 상태를 시그널링 할 수 있다는 점에서 원하는 경우 예측 가능한 스케줄링의 구현을 허용한다.


그래서… 뮤텍스를 항상 잠금 해제 한 채로두고 기다린 후 바로 잠그고 기다린 후에 바로 잠금을 해제 하지 않는 이유 가 있습니까?
ELLIOTTCABLE

또한 뮤텍스는 대기 스레드와 신호 스레드 간의 잠재적 인 경쟁을 해결합니다. 상태를 변경하고 신호를 보낼 때 뮤텍스가 항상 잠겨있는 한 신호를 놓치지 않고 영원히 자고있는 것을 발견 할 수 없습니다.
Hasturkun

그래서 ... 내가해야 기다립니다 -에 - 뮤텍스 conditionvar의 뮤텍스에서 conditionvar에 대기 전에? 나는 전혀 이해하지 못한다.
ELLIOTTCABLE

2
@elliottcable : 뮤텍스를 잡지 않고 기다릴 지 말아야하는지 어떻게 알 수 있습니까? 당신이 기다리는 것이 방금 일어난다면?
David Schwartz

1

조건 변수의 실제 예를 원한다면 클래스에서 연습을했습니다.

#include "stdio.h"
#include "stdlib.h"
#include "pthread.h"
#include "unistd.h"

int compteur = 0;
pthread_cond_t varCond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex_compteur;

void attenteSeuil(arg)
{
    pthread_mutex_lock(&mutex_compteur);
        while(compteur < 10)
        {
            printf("Compteur : %d<10 so i am waiting...\n", compteur);
            pthread_cond_wait(&varCond, &mutex_compteur);
        }
        printf("I waited nicely and now the compteur = %d\n", compteur);
    pthread_mutex_unlock(&mutex_compteur);
    pthread_exit(NULL);
}

void incrementCompteur(arg)
{
    while(1)
    {
        pthread_mutex_lock(&mutex_compteur);

            if(compteur == 10)
            {
                printf("Compteur = 10\n");
                pthread_cond_signal(&varCond);
                pthread_mutex_unlock(&mutex_compteur);
                pthread_exit(NULL);
            }
            else
            {
                printf("Compteur ++\n");
                compteur++;
            }

        pthread_mutex_unlock(&mutex_compteur);
    }
}

int main(int argc, char const *argv[])
{
    int i;
    pthread_t threads[2];

    pthread_mutex_init(&mutex_compteur, NULL);

    pthread_create(&threads[0], NULL, incrementCompteur, NULL);
    pthread_create(&threads[1], NULL, attenteSeuil, NULL);

    pthread_exit(NULL);
}

1

그것은 개념적 필요보다는 특정한 디자인 결정 인 것으로 보인다.

pthreads 문서에 따라 뮤텍스가 분리되지 않은 이유는 뮤텍스를 결합하여 성능이 크게 향상되어 뮤텍스를 사용하지 않으면 일반적인 경쟁 조건으로 인해 거의 항상 수행 될 것으로 기대하기 때문입니다.

https://linux.die.net/man/3/pthread_cond_wait

뮤텍스 및 조건 변수의 특징

뮤텍스 획득 및 릴리스는 조건 대기에서 분리되도록 제안되었습니다. 실제로 실시간 구현을 용이하게하는 작업의 결합 된 특성이기 때문에 거부되었습니다. 이러한 구현은 호출자에게 투명한 방식으로 조건 변수와 뮤텍스 사이에서 우선 순위가 높은 스레드를 원자 적으로 이동할 수 있습니다. 이를 통해 추가 컨텍스트 전환을 방지하고 대기 스레드에 신호를 보낼 때보다 결정적인 뮤텍스를 얻을 수 있습니다. 따라서 공정성 및 우선 순위 문제는 스케줄링 원칙에 의해 직접 처리 될 수 있습니다. 또한 현재 조건 대기 작업이 기존 사례와 일치합니다.


0

그것에 대해 많은 주석이 있지만 다음 예제를 통해 설명하고 싶습니다.

1 void thr_child() {
2    done = 1;
3    pthread_cond_signal(&c);
4 }

5 void thr_parent() {
6    if (done == 0)
7        pthread_cond_wait(&c);
8 }

코드 스 니펫에 어떤 문제가 있습니까? 계속 진행하기 전에 어느 정도 숙고하십시오.


이 문제는 정말 미묘합니다. 부모가를 호출 thr_parent()한 다음 그 값을 검사하면 그 값 done이 확인 0되어 잠자기 상태가됩니다. 그러나 전화가 잠들기 위해 대기하기 직전에 부모는 6-7 줄 사이에 중단되고 아이는 달려갑니다. 자식은 상태 변수 done1및 신호로 변경 하지만 대기중인 스레드가 없으므로 스레드가 깨어나지 않습니다. 부모가 다시 달리면 영원히 잠이 듭니다.

잠금을 개별적으로 획득 한 상태에서 수행하면 어떻게됩니까?

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