pthread_cond_wait versus Semaphor

Lesezeit: 7 Minuten

Benutzeravatar von shodanex
Schodanex

Was sind die Vor- / Nachteile der Verwendung pthread_cond_wait oder mit einem Semaphor? Ich warte auf eine Zustandsänderung wie folgt:

pthread_mutex_lock(&cam->video_lock);
while(cam->status == WAIT_DISPLAY) {
    pthread_cond_wait(&cam->video_cond, &cam->video_lock);
}
pthread_mutex_unlock(&cam->video_lock);

Mit einem richtig initialisierten Semaphor könnte ich es so machen:

while(cam->status == WAIT_DISPLAY) {
    sem_wait(&some_semaphore);
}

Was sind die Vor- und Nachteile der einzelnen Methoden?

  • Ich habe gerade festgestellt, dass “ordnungsgemäß initialisiertes Semaphor” schlecht definiert ist. Ist die Semaphore auf 1 oder auf 0 gesetzt? Ich würde sagen, es sollte auf 0 gesetzt werden. Schützt die Semaphore dann den Kamera-> Status oder nicht?

    – Blaisorlade

    1. Juni 2014 um 22:45 Uhr

  • Im zweiten Ausschnitt wird Ihr Thread, wie in anderen Antworten erwähnt, blockiert, während Mutex nicht freigegeben wird. Also dein sem_wait -Methode wird niemals zurückkehren, da kein anderer Thread den Mutex erwerben und aufrufen kann sem_signal. Ich werde jedoch nicht was tun, wenn ich vorher Mutex freigebe sem_wait und fordern Sie es nach dem Warten erneut an. Ich weiß, dass diese Schritte nicht atomar sind, also was wird passieren?

    – sevenkplus

    3. Oktober 2016 um 15:31 Uhr


Benutzeravatar von Steve Jessop
Steve Jessop

Ein Semaphor ist für ein Producer-Consumer-Modell geeignet, obwohl es andere Verwendungen hat. Ihre Programmlogik ist dafür verantwortlich, dass für die Anzahl der Wartezeiten die richtige Anzahl von Beiträgen erstellt wird. Wenn Sie eine Semaphore posten und noch niemand darauf wartet, dann fahren sie sofort fort, wenn sie warten. Wenn Ihr Problem so ist, dass es anhand des Zählwerts einer Semaphore erklärt werden kann, sollte es mit einer Semaphore einfach zu lösen sein.

Eine Bedingungsvariable ist in mancher Hinsicht etwas nachsichtiger. Sie können zum Beispiel cond_broadcast verwenden, um alle Kellner aufzuwecken, ohne dass der Produzent weiß, wie viele es sind. Und wenn Sie eine Condvar cond_signalisieren, auf die niemand wartet, passiert nichts. Das ist gut, wenn Sie nicht wissen, ob es einen interessierten Zuhörer geben wird. Aus diesem Grund sollte der Zuhörer auch immer den Zustand mit gehaltenem Mutex überprüfen, bevor er wartet – wenn er dies nicht tut, kann er ein Signal verpassen und nicht bis zum nächsten aufwachen (was niemals sein könnte).

Eine Bedingungsvariable ist also geeignet, interessierten Parteien mitzuteilen, dass sich der Zustand geändert hat: Sie erwerben den Mutex, ändern den Zustand, signalisieren (oder senden) die Condvar und geben den Mutex frei. Wenn dies Ihr Problem beschreibt, befinden Sie sich im Condvar-Territorium. Wenn verschiedene Zuhörer an verschiedenen Zuständen interessiert sind, können Sie einfach senden, und sie werden nacheinander aufwachen, herausfinden, ob sie den gewünschten Zustand gefunden haben, und wenn nicht, erneut warten.

Es ist in der Tat sehr knorrig, so etwas mit einem Mutex und einem Semaphor zu versuchen. Das Problem tritt auf, wenn Sie den Mutex nehmen, einen Status überprüfen und dann auf Änderungen am Semaphor warten möchten. Wenn Sie den Mutex nicht atomar freigeben und auf den Semaphor warten können (was in pthreads nicht möglich ist), warten Sie am Ende auf den Semaphor, während Sie den Mutex gedrückt halten. Dadurch wird der Mutex blockiert, was bedeutet, dass andere ihn nicht nehmen können, um die Änderung vorzunehmen, die Ihnen wichtig ist. Sie werden also versucht sein, einen weiteren Mutex auf eine Weise hinzuzufügen, die von Ihren spezifischen Anforderungen abhängt. Und vielleicht noch ein Semaphor. Das Ergebnis ist im Allgemeinen falscher Code mit schädlichen Rennbedingungen.

Bedingungsvariablen umgehen dieses Problem, da der Aufruf von cond_wait den Mutex automatisch freigibt und ihn für die Verwendung durch andere freigibt. Der Mutex wird wiederhergestellt, bevor cond_wait zurückkehrt.

IIRC ist es möglich, eine Art Condvar nur mit Semaphoren zu implementieren, aber wenn der Mutex, den Sie implementieren, um mit der Condvar zu gehen, Trylock haben muss, dann ist es ein ernsthafter Kopfkratzer, und zeitgesteuerte Wartezeiten sind vorbei. Nicht empfohlen. Gehen Sie also nicht davon aus, dass alles, was Sie mit einer Condvar machen können, auch mit Semaphoren gemacht werden kann. Außerdem können Mutexe natürlich nette Verhaltensweisen haben, die Semaphoren fehlen, hauptsächlich die Vermeidung von Prioritätsumkehrungen.

Benutzeravatar von freespace
Freiraum

Mit Bedingungen können Sie einige Dinge tun, die mit Semaphoren nicht möglich sind.

Angenommen, Sie haben einen Code, der einen Mutex namens m. Es muss jedoch warten, bis ein anderer Thread seine Aufgabe beendet hat, also wartet es auf ein aufgerufenes Semaphor s. Jetzt irgendein Thread was braucht m wird blockiert, obwohl der Thread welche hat m wartet auf s. Solche Situationen können mit Bedingungssätzen gelöst werden. Wenn Sie auf eine Bedingung warten, wird der aktuell gehaltene Mutex freigegeben, sodass andere Threads den Mutex abrufen können. Also zurück zu unserem Beispiel, und angenommen, bedingt c wurde stattdessen verwendet s. Unser Thread erwirbt jetzt mund dann bedingtes Warten auf c. Dies löst m damit andere Threads fortfahren können. Wann c wird verfügbar, m wiedererlangt, und unser ursprünglicher Faden kann munter seinen Weg fortsetzen.

Bedingte Variablen können Sie auch lassen alle Threads, die auf eine bedingte Variable warten, um fortzufahren pthread_cond_broadcast. Darüber hinaus ermöglicht es Ihnen auch, a zeitgesteuert warten damit Sie nicht ewig warten müssen.

Natürlich benötigen Sie manchmal keine bedingten Variablen, daher kann je nach Ihren Anforderungen die eine oder andere besser sein.

  • Dies ist eine gute Antwort. Um der Beschreibung noch etwas hinzuzufügen, was Konditionale relativ zu der beschriebenen Kombination aus Mutex und Semaphor einzigartig macht, ist, dass die Bedingung das Mutex/Semaphor-Paar atomar manipuliert!!

    – Großer Jeff

    23. September 2008 um 0:41 Uhr

Das 2. Snippet ist rassig, tun Sie das nicht.

Die anderen Antworten haben eine nette Diskussion über die relativen Vorzüge; Ich füge das einfach hinzu pthread_cond_broadcast ist ein klarer Vorteil von Bedingungsvariablen.

Darüber hinaus bin ich es eher gewohnt, Variablen dafür zu konditionieren, da sie das sind, was Sie in Java verwenden, auch weil sie Ihnen helfen, Rennen beim Überprüfen der gemeinsam genutzten Flags zu vermeiden.

Tatsächlich haben Sie im 2. Snippet keine Sperre, die das Lesen von cam->status schützt, sodass über ein Datenrennen darauf zugegriffen wird. Die meisten Plattformen lassen Sie in diesem speziellen Beispiel damit durchkommen, aber das hat eine undefinierte Semantik, durch POSIX und durch das Speichermodell der nächsten C/C++-Standards.

Tatsächlich ist eine echte Wettlaufbedingung möglich, wenn ein anderer Thread eine neue Nockenstruktur zuweist und die Nocke überschreibt; Der wartende Thread sieht möglicherweise die Aktualisierung des ‘cam’-Zeigers, ohne die Initialisierung von cam->status zu sehen. In der Tat fordert das 2. Snippet Ärger, in diesem Fall und im Allgemeinen.

http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/

  • Tatsächlich könnte im zweiten Snippet die Semaphore selbst das Status-Flag schützen (oder nicht) (obwohl ich mir kein gutes Sperrprotokoll dafür vorstellen kann).

    – Blaisorlade

    1. Juni 2014 um 22:48 Uhr

In Ihrem zweiten Ausschnitt erhalten Sie die Sperre viele Male, ohne sie freizugeben.

Im Allgemeinen kann der Zustand, auf den Sie warten, vollständig durch ein Semaphor ausgedrückt werden, dann können Sie genau das verwenden. Eine Sperrstruktur ist kleiner und erfordert weniger atomare Operationen zum Prüfen/Setzen/Freigeben.

Andernfalls, wenn der Zustand komplex ist und verschiedene Teile des Codes auf verschiedene Bedingungen derselben Variablen warten (z. B. hier möchten Sie x<10; dort möchten Sie y>x), verwenden Sie cond_wait.

while(cam->status == WAIT_DISPLAY) {
    sem_wait(&some_semaphore);
}

Das ist völlig falsch. Dies ist anfällig für Rennbedingungen. Bis der Thread auf sem_Wait blockiert, gilt die Bedingung cam->status == WAIT_DISPLAY möglicherweise nicht mehr im System, da ein anderer Thread sie möglicherweise geändert hat. Also schläft Ihr Thread jetzt aus allen falschen Gründen.

1408450cookie-checkpthread_cond_wait versus Semaphor

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

Privacy policy