it-swarm.com.de

Verständnis von pthread_cond_wait () und pthread_cond_signal ()

Im Allgemeinen werden pthread_cond_wait() und pthread_cond_signal() wie folgt aufgerufen:

//thread 1:
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
do_something()
pthread_mutex_unlock(&mutex);

//thread 2:
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);  
pthread_mutex_unlock(&mutex);

Die Schritte sind

  1. pthread_cond_wait(&cond, &mutex); wird aufgerufen und gibt den Mutex frei

  2. Thread 2 sperrt den Mutex und ruft pthread_cond_signal() auf, wodurch der Mutex entsperrt wird

  3. In Thread 1 wird pthread_cond_wait() aufgerufen und der Mutex wieder gesperrt

Jetzt in Thread 2, nachdem pthread_cond_signal() aufgerufen wurde, pthread_mutex_unlock(&mutex) ausgeführt wird, scheint es mir, dass es den Mutex entsperren möchte, der jetzt von Thread 1 gesperrt ist Ist etwas falsch in meinem Verständnis?

Außerdem scheint es mir auch, dass pthread_cond_wait() von nur einem Thread für dasselbe Cond-Mutex-Paar aufgerufen werden kann. Es gibt jedoch den Spruch "Die Funktion pthread_cond_signal () soll mindestens einen der Threads entsperren, die für die angegebene Bedingungsvariable cond gesperrt sind (falls Threads für cond gesperrt sind)." Es bedeutet also, dass pthread_cond_wait() von vielen Threads für dasselbe Cond-Mutex-Paar aufgerufen werden kann.

33
user1944267

pthread_cond_signal gibt den Mutex nicht frei (da er keinen Verweis auf den Mutex hat, wie kann er wissen, was zu entsperren ist?) Tatsächlich muss das Signal keine Verbindung zum Mutex haben. Der Signalisierungs-Thread muss den Mutex nicht enthalten, bei den meisten Algorithmen, die auf Bedingungsvariablen basieren, jedoch.

pthread_cond_wait gibt den Mutex frei, kurz bevor er in den Ruhemodus wechselt (wie Sie bemerken), fordert dann aber den Mutex wieder an (was möglicherweise ein Warten erfordert), wenn er signalisiert wird, bevor er aufwacht. Wenn also der Signalisierungs-Thread den Mutex enthält (im Normalfall), wird der wartende Thread erst fortgesetzt, wenn der Signalisierungs-Thread auch den Mutex entsperrt.

Die übliche Verwendung von Bedingungsvariablen ist wie folgt:

thread 1:
    pthread_mutex_lock(&mutex);
    while (!condition)
        pthread_cond_wait(&cond, &mutex);
    /* do something that requires holding the mutex and condition is true */
    pthread_mutex_unlock(&mutex);

thread2:
    pthread_mutex_lock(&mutex);
    /* do something that might make condition true */
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);

Die beiden Threads haben eine gemeinsame Datenstruktur, auf die der Mutex den Zugriff schützt. Der erste Thread möchte warten, bis eine Bedingung erfüllt ist, und dann sofort eine Operation ausführen (ohne die Möglichkeit einer Racebedingung, dass ein anderer Thread zwischen die Bedingungsprüfung und die Aktion tritt und die Bedingung auf falsch setzt). Der zweite Thread führt möglicherweise etwas aus Wenn die Bedingung erfüllt ist, muss sie jeden wecken, der darauf wartet.

75
Chris Dodd

Hier ein typisches Beispiel: Thread 1 wartet auf eine Bedingung, die von Thread 2 erfüllt werden kann .

Wir verwenden einen Mutex und eine Bedingung.

pthread_mutex_t mutex;
pthread_cond_t condition;

faden 1:

pthread_mutex_lock(&mutex); //mutex lock
while(!condition){
    pthread_cond_wait(&condition, &mutex); //wait for the condition
}

/* do what you want */

pthread_mutex_unlock(&mutex);

faden 2:

pthread_mutex_lock(&mutex);

/* do something that may fulfill the condition */

pthread_mutex_unlock(&mutex);
pthread_cond_signal(&condition); //wake up thread 1

Bearbeiten

Wie Sie im pthread_cond_wait Handbuch sehen können :

Es gibt den Mutex atomar frei und bewirkt, dass der aufrufende Thread die Bedingungsvariable cond blockiert. atomisch bedeutet hier "atomisch in Bezug auf den Zugriff eines anderen Threads auf den Mutex und dann auf die Bedingungsvariable".

7
Ludzu