Ein Semaphor ist sauber zu einem Produzenten-Verbraucher-Modell geeignet, obwohl es andere Verwendungen hat. Ihre Programmlogik ist dafür verantwortlich, dass die richtige Anzahl von Posts für die Anzahl der Wartezeiten erstellt wird. Wenn du einen Semaphor postest und noch niemand darauf wartet, dann machen sie sofort weiter. Wenn Ihr Problem so ist, dass es in Bezug auf den Zählwert eines Semaphors erklärt werden kann, sollte es leicht mit einem Semaphor zu lösen sein.
Eine Zustandsvariable ist in mancher Hinsicht etwas fehlerverzeihender. Sie können zum Beispiel cond_broadcast verwenden, um alle Kellner aufzuwecken, ohne dass der Produzent weiß, wie viele es sind. Und wenn Sie einen Condvar signalisieren, während niemand darauf wartet, passiert nichts. Das ist gut, wenn Sie nicht wissen, ob ein Hörer interessiert ist. Es ist auch der Grund, warum der Zuhörer den Zustand immer mit dem vor dem Warten gehaltenen Mutex überprüfen sollte - wenn sie dies nicht tun, können sie ein Signal verpassen und nicht bis zum nächsten aufwachen (was niemals sein könnte).
So eine Zustandsvariable ist geeignet, interessierten Parteien mitzuteilen, dass sich der Status geändert hat: Sie erwerben den Mutex, ändern den Status, signalisieren (oder senden) den Condvar und geben den Mutex frei. Wenn dies Ihr Problem beschreibt, befinden Sie sich im Condvar-Gebiet. Wenn unterschiedliche Zuhörer an verschiedenen Zuständen interessiert sind, können Sie sie einfach senden, und sie werden dann nacheinander aufwachen, herausfinden, ob sie den gewünschten Zustand gefunden haben und wenn nicht, noch einmal warten.
Es ist in der Tat sehr gnadenlos, so etwas mit einem Mutex und einem Semaphor zu versuchen. Das Problem tritt auf, wenn Sie den Mutex nehmen, einen Zustand überprüfen und dann auf dem Semaphor auf Änderungen warten wollen. Wenn Sie den Mutex nicht atomar freigeben und auf den Semaphor warten können (was bei Pthreads nicht möglich ist), warten Sie auf den Semaphor, während Sie den Mutex halten. Dies blockiert den Mutex, was bedeutet, dass andere es nicht nehmen können, um die Änderung vorzunehmen, die dir wichtig ist. Sie werden also versucht sein, einen weiteren Mutex hinzuzufügen, der von Ihren spezifischen Anforderungen abhängt. Und vielleicht noch ein Semaphor. Das Ergebnis ist im Allgemeinen ein falscher Code mit schädlichen Rennbedingungen.
Bedingungsvariablen umgehen dieses Problem, da der Aufruf von cond_wait den Mutex automatisch freigibt und ihn für andere Benutzer freigibt. Der Mutex wird zurückgewonnen, bevor cond_wait zurückkehrt.
IIRC Es ist möglich, eine Art Condvar nur mit Semaphoren zu implementieren, aber wenn der Mutex, den du implementierst, um mit dem Condvar zu arbeiten, trelock benötigt, dann ist es ein ernsthafter Kopfkratzer, und zeitgesteuerte Wartezeiten sind out . Nicht empfohlen. Gehen Sie also nicht davon aus, dass irgendetwas, was Sie mit einer Condvar machen können, mit Semaphoren gemacht werden kann. Außerdem können Mutexe natürlich nette Verhaltensweisen haben, denen Semaphore fehlen, hauptsächlich die Prioritätsinversionsvermeidung.
Ich habe erkannt, dass „richtig initialisiert Semaphore“ ist schlecht definiert. Ist der Semaphor auf 1 oder auf 0 gesetzt? Ich würde sagen, es sollte auf 0 gesetzt werden. Dann schützt das Semaphor cam-> Status oder nicht? – Blaisorblade
Im zweiten Snippet, wie in anderen Antworten erwähnt, wird Ihr Thread blockiert, während Mutex nicht freigegeben ist. Also wird Ihre 'sem_wait' Methode niemals zurückkehren, da kein anderer Thread den Mutex erzwingen und' sem_signal' aufrufen kann. Allerdings werde ich nicht was tun, wenn ich Mutex vor 'sem_wait' freigebe und nach dem Warten wieder benötige. Ich weiß, dass diese Schritte nicht atomar sind, also was wird passieren? – sevenkplus