Wenn Sie den Mutex nicht im Codepfad sperren, der den Zustand und die Signale ändert, können Sie das Aufwecken verlieren. Betrachten Sie dieses Prozesspaar:
Prozess A:
pthread_mutex_lock(&mutex);
while (condition == FALSE)
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
Prozess B (falsch):
condition = TRUE;
pthread_cond_signal(&cond);
Betrachten Sie dann diese mögliche Verschachtelung von Anweisungen, wobei condition
Folgendes beginnt FALSE
:
Process A Process B
pthread_mutex_lock(&mutex);
while (condition == FALSE)
condition = TRUE;
pthread_cond_signal(&cond);
pthread_cond_wait(&cond, &mutex);
Das condition
ist jetzt TRUE
, aber Prozess A wartet nicht mehr auf die Bedingungsvariable - er hat das Wecksignal verpasst. Wenn wir Prozess B ändern, um den Mutex zu sperren:
Prozess B (richtig):
pthread_mutex_lock(&mutex);
condition = TRUE;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
... dann kann das oben genannte nicht auftreten; Das Aufwachen wird nie fehlen.
(Beachten Sie, dass Sie können tatsächlich die bewegen pthread_cond_signal()
sich nach dem pthread_mutex_unlock()
, aber in weniger optimalen Planung von Threads zur Folge haben kann, und Sie haben notwendigerweise den Mutex gesperrt bereits in diesem Codepfad aufgrund Änderung der Bedingung selbst).
pthread_signal_cond()
kann der nach dem Mutex-Unlock verschoben werden, obwohl es wahrscheinlich besser ist, dies nicht zu tun . Es ist vielleicht richtiger zu sagen, dass Sie an dem Punkt, an dem Sie anrufenpthread_signal_cond()
, den Mutex bereits gesperrt haben müssen, um die Bedingung selbst zu ändern.pthread_cond_timedwait()
oder diepthread_cond_wait()
Operation angegeben hat, wird eine dynamische Bindung zwischen diesem Mutex und der Bedingungsvariablen gebildet, die so lange wie gültig bleibt Mindestens ein Thread ist für die Bedingungsvariable blockiert. Während dieser Zeit ist die Auswirkung eines Versuchs eines Threads, mit einem anderen Mutex auf diese Bedingungsvariable zu warten, undefiniert. "Nach diesem Handbuch:
Die Bedeutung der vorhersagbaren Planungsverhaltensangabe wurde von Dave Butenhof (Autor von Programming with POSIX Threads ) auf comp.programming.threads erläutert und ist hier verfügbar .
quelle
caf, in Ihrem Beispielcode ändert sich Prozess B,
condition
ohne zuerst den Mutex zu sperren. Wenn Prozess B den Mutex während dieser Änderung einfach gesperrt und dann den Mutex vor dem Aufruf immer noch entsperrt hatpthread_cond_signal
, gibt es kein Problem - habe ich Recht damit?Ich glaube intuitiv, dass die Position des Cafés korrekt ist: Anrufen
pthread_cond_signal
ohne das Mutex-Schloss zu besitzen, ist eine schlechte Idee. Aber das Beispiel des Cafés ist jedoch kein Beweis für diese Position. Es ist lediglich ein Beweis für die viel schwächere (praktisch selbstverständliche) Position, dass es eine schlechte Idee ist, den durch einen Mutex geschützten gemeinsamen Status zu ändern, es sei denn, Sie haben diesen Mutex zuerst gesperrt.Kann jemand einen Beispielcode bereitstellen, in dem ein Aufruf
pthread_cond_signal
gefolgt von einempthread_mutex_unlock
korrekten Verhalten, ein Aufrufpthread_mutex_unlock
gefolgt von einempthread_cond_signal
falschen Verhalten jedoch ein korrektes Verhalten ergibt?quelle
pthread_cond_signal
nachherpthread_mutex_unlock
zu einem verlorenen Aufwecken führen kann, da das Signal als "falscher" Thread abgefangen wird, der blockiert wurde, nachdem die Änderung im Prädikat festgestellt wurde. Dies ist nur dann ein Problem, wenn dieselbe Bedingungsvariable für mehr als ein Prädikat verwendet werden kann und Sie sie nicht verwenden. Dies istpthread_cond_broadcast
ohnehin ein seltenes und fragiles Muster.