Warum wird eine While-Schleife um Pthread-Wartebedingungen benötigt?

Lesezeit: 3 Minuten

Benutzeravatar von Emiliano
Emiliano

Ich lerne pthread und Wartebedingungen. Soweit ich das beurteilen kann, sieht ein typischer wartender Thread folgendermaßen aus:

pthread_mutex_lock(&m);
while(!condition)
     pthread_cond_wait(&cond, &m);
// Thread stuff here
pthread_mutex_unlock(&m);

Was ich nicht verstehe ist, warum die Zeile while(!condition) ist notwendig, auch wenn ich benutze pthread_cond_signal() um den Thread aufzuwecken.

Ich kann das verstehen, wenn ich benutze pthread_cond_broadcast() Ich muss den Zustand testen, weil ich aufwache alle wartende Threads und einer von ihnen kann die Bedingung wieder falsch machen, bevor der Mutex entsperrt wird (und somit die Ausführung auf einen anderen aufgeweckten Thread übertragen wird, der zu diesem Zeitpunkt nicht ausgeführt werden sollte). Aber wenn ich benutze pthread_cond_signal() Ich wache gerade auf eines Thread, also muss die Bedingung wahr sein. Der Code könnte also so aussehen:

pthread_mutex_lock(&m);
pthread_cond_wait(&cond, &m);
// Thread stuff here
pthread_mutex_unlock(&m);

Ich habe etwas über Störsignale gelesen, die auftreten können. Ist das (und nur das) der Grund? Warum sollte ich Störsignale haben? Oder fällt mir etwas anderes nicht ein?

Ich nehme an, der Signalcode ist wie folgt:

pthread_mutex_lock(&m);
condition = true;
pthread_cond_signal(&cond); // Should wake up *one* thread
pthread_mutex_unlock(&m);

Der eigentliche Grund, warum Sie pthread_cond_wait in eine While-Schleife stecken sollten, ist nicht das falsche Aufwachen. Selbst wenn Ihre Bedingungsvariable kein falsches Aufwachen hätte, würden Sie die Schleife dennoch benötigen, um einen häufigen Fehlertyp abzufangen. Wieso den? Überlegen Sie, was passieren kann, wenn mehrere Threads auf dieselbe Bedingung warten:

Thread 1                         Thread 2           Thread 3
check condition (fails)
(in cond_wait) unlock mutex
(in cond_wait) wait
                                 lock mutex
                                 set condition
                                 signal condvar
                                 unlock mutex
                                                    lock mutex
                                                    check condition (succeeds)
                                                    do stuff
                                                    unset condition
                                                    unlock mutex
(in cond_wait) wake up
(in cond_wait) lock mutex
<thread is awake, but condition
is unset>

Das Problem hier ist, dass der Thread den Mutex freigeben muss, bevor er wartet, was möglicherweise einem anderen Thread erlaubt, das zu „stehlen“, worauf dieser Thread gewartet hat. Wenn nicht garantiert ist, dass nur ein Thread auf diese Bedingung warten kann, ist es falsch anzunehmen, dass die Bedingung gültig ist, wenn ein Thread aufwacht.

  • exakt. hochgestimmt. Dies sollte mehr Aufmerksamkeit erregen als die akzeptierte Antwort.

    – v.oddou

    18. April 2014 um 1:54 Uhr

Benutzeravatar von Steve Jessop
Steve Jessop

Angenommen, Sie überprüfen die Bedingung nicht. Dann können Sie normalerweise die folgende schlechte Sache nicht vermeiden (zumindest können Sie es nicht in einer Codezeile vermeiden):

 Sender                             Receiver
locks mutex
sets condition
signals condvar, but nothing 
  is waiting so has no effect
releases mutex
                                    locks mutex
                                    waits. Forever.

Natürlich könnte Ihr zweites Codebeispiel dies vermeiden, indem Sie Folgendes tun:

pthread_mutex_lock(&m);
if (!condition) pthread_cond_wait(&cond, &m);
// Thread stuff here
pthread_mutex_unlock(&m);

Dann wäre es sicher so, wenn es immer nur höchstens einen Empfänger gibt, und wenn cond_signal wäre das einzige, was es aufwecken könnte, dann würde es immer nur aufwachen, wenn die Bedingung gesetzt ist und würde daher keine Schleife benötigen. nos behandelt, warum das zweite “if” nicht wahr ist.

  • Ich verstehe, also wird aus einem logischen Grund (endloses Warten) ein “wenn” benötigt, aber aufgrund von Implementierungsproblemen (Störsignale) wird tatsächlich eine Weile benötigt.

    – Emiliano

    16. Juli 2009 um 11:40 Uhr

  • Ja, als ich zum ersten Mal die pthreads-Bibliothek benutzte, stellte ich dieselbe Frage. Ich habe die Überprüfung einer Zustandsvariablen ausgelassen und mein Programm würde signalisieren, bevor das Warten auftrat. Dies ist der ganze Sinn der Wait/Signal-Funktionen. Warten und Signalisieren einer Mutex-geschützten Änderung des Speicherzustands.

    – iss_eine_Zitrone

    25. März 2011 um 15:09 Uhr

1409360cookie-checkWarum wird eine While-Schleife um Pthread-Wartebedingungen benötigt?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy