Hallo,
wir haben eine Semaphore, welche sehr oft ausgelöst wird, bevor es
abgefragt wird (ist aber auch so gewollt).
Jetzt suchen wir eine möglichkeit die Semaphore auf einmal wieder auf 0
zu setzen. Quasi ein reset. Das haben wir aber nichts zu gefunden.
Haben es dann einfach mit sem_init neu gemacht. Hat auch funktioniert
(in einem fall zumindest). Aber es heißt auch
Initializing a semaphore that has already been initialized results in
undefined behavior.
Jetzt fallen mir nur die möglichkeiten ein
1)
sem_destroy
und dann neu initialisieren mit
sem_init
2)
sem_getvalue
und dann eine for-schleife mit
sem_post
Der wert ist bei ca. 30000.
Was wäre schneller/schöner? Gibt es sonst keine Möglichkeit den Wert
wieder zurückzusetzen?
Johannes schrieb:> Was wäre schneller/schöner? Gibt es sonst keine Möglichkeit den Wert> wieder zurückzusetzen?
Beides schlecht, der Sinn einer Semaphore ist, dass sie in den Kontexten
dekrementiert wird, wo sie auch inkrementiert wurde. Dann kommt man
automatisch wieder auf 0.
Johannes schrieb:> wir haben eine Semaphore, welche sehr oft ausgelöst wird, bevor es> abgefragt wird (ist aber auch so gewollt).
Ich glaube da musst du den Sinn dahinter mal genauer beschreiben, eine
reine Semaphore ist wohl nicht die Lösung.
Das verstehe ich nicht. Mit Semaphoren soll ja etwas signalisiert
werden. Du hast 30.000 Signale abgefeuert, und jetzt sind die auf einen
Schlag alle ungültig und sollen ungenutzt verworfen werden? Bist du
sicher, dass Semaphoren das geeignete Mittel für deinen Anwendungsfall
sind?
Rolf M. schrieb:> Das verstehe ich nicht. Mit Semaphoren soll ja etwas signalisiert> werden. Du hast 30.000 Signale abgefeuert, und jetzt sind die auf einen> Schlag alle ungültig und sollen ungenutzt verworfen werden? Bist du> sicher, dass Semaphoren das geeignete Mittel für deinen Anwendungsfall> sind?
Wie kommst du auf Signale?
Johannes schrieb:> Jetzt fallen mir nur die möglichkeiten ein> 1)> sem_destroy
Ebenfalls undefiniert wenn noch sem_wait() aktiv sind.
> 2)> sem_getvalue> und dann eine for-schleife mit> sem_post
Nein.
a) Da du nicht weißt ob noch andere Programmteile an der Semaphore
rumbasteln reicht einmal sem_getvalue() vor der Schleife nicht. Der Wert
kann sich wärend die Schleife läuft ändern.
b) sem_post() erhöht die Semaphore. Wie willst du durch Inkrementieren
auf 0 kommen?
sem_trywait() ohne sem_getvalue() wäre möglich.
> Der wert ist bei ca. 30000.> Was wäre schneller/schöner?
Eine bessere Programmstruktur. Das klingt sehr danach dass jemand
besonders Clever sein wollte aber sich in eine Ecke programmiert hat.
Jetzt, statt den Fehler zuzugeben und zu beseitigen, soll was
zusammengebastelt werden.
Zu jedem sem_post() gehört ein sem_wait() im Code.
cppbert schrieb:> Wie kommst du auf Signale?Rolf M. schrieb:> Mit Semaphoren soll ja etwas signalisiert werden.
Es wurde also 30.000 mal etwas signalisiert. Wie Felix schon schreibt,
gehört das inkrementieren und dekrementieren normalerweise zusammen, und
da sollte nix auseinanderlaufen. Die Frage ist also, warum das jetzt
alles ungehört verworfen werden soll.
Klingt als bräuchtest du eher eine Condition Variable statt einer
Semaphore. Dort kann man Zähler beliebig setzen. Man muss aber aufpassen
es genau richtig zu machen um keine Ereignisse zu verpassen.
Rolf M. schrieb:> Rolf M. schrieb:>> Mit Semaphoren soll ja etwas signalisiert werden.>> Es wurde also 30.000 mal etwas signalisiert.
das mit dem Signalisieren hast du als 1. geschrieben - ist aber würde
ich sagen der falsche Begriff - es geht bei Semaphoren doch um die
Absicherung von Ressourcen die nur eine bestimmte Menge an
Parallel-Zugriffen erlauben, das kann was mit signalisieren zu tun haben
muss es aber auch überhaupt nicht
cppbert schrieb:> Rolf M. schrieb:>> Rolf M. schrieb:>>> Mit Semaphoren soll ja etwas signalisiert werden.>>>> Es wurde also 30.000 mal etwas signalisiert.>> das mit dem Signalisieren hast du als 1. geschrieben - ist aber würde> ich sagen der falsche Begriff - es geht bei Semaphoren doch um die> Absicherung von Ressourcen die nur eine bestimmte Menge an> Parallel-Zugriffen erlauben, das kann was mit signalisieren zu tun haben> muss es aber auch überhaupt nicht
Ich denke, Du irrst Dich.
Ein "Semaphor" ist zunächst das pyhsische Mittel um ein "Signal" zu
geben. In der Informatik ist das eine Datenstruktur, in der
Informationen, in der physischen Form von Spannungen in Speicherstellen,
gespeichert sind.
Im übrigen irrst Du Dich m.M.n. auch mit der Aussage, dass die
Absicherung von Resourcen unter Umständen nichts mit Signalisierung zu
tun haben kann.
Da Informationen - und die Tatsache das eine Resource belegt ist, ist
eine Information -, nur durch Signal übertragen resp. repräsentiert
werden können, hat das zwingend grundsätzlich mit Signalen zu tun.
Siehe die entsprechenden Einträge in der Wikipedia unter "Signal" und
"Semaphor".
So wie im Anhang könnte man es mit einer Condition Variable machen. Der
main-Thread "sendet" Signale indem er den signalCounter erhöht, und der
zweite Thread empfängt sie. Er setzt dabei jedes mal den signalCounter
auf 0, d.h. konsumiert viele Signale auf einmal. Der main-Thread könnte
den Counter auch auf 0 zurück setzen oder sonstwie beliebig bearbeiten,
solange das innerhalb des Mutex passiert. Die Condition Variable stellt
hier sicher, dass man keine Ereignisse verpasst.
Der selbe Mechanismus wird auch benutzt um den Thread zu beenden; "run"
wird, geschützt durch den Mutex, auf "false" gesetzt, um Beendigung zu
signalisieren. Die Condition Variable wird benutzt, um den Thread in
diesem Fall sofort aufzuwecken sodass er dann zurückkehren kann.
cppbert schrieb:> Rolf M. schrieb:>> Rolf M. schrieb:>>> Mit Semaphoren soll ja etwas signalisiert werden.>>>> Es wurde also 30.000 mal etwas signalisiert.>> das mit dem Signalisieren hast du als 1. geschrieben
Deshalb hat mich deine Rückfrage etwas verwundert.
> - ist aber würde ich sagen der falsche Begriff - es geht bei Semaphoren doch> um die Absicherung von Ressourcen die nur eine bestimmte Menge an> Parallel-Zugriffen erlauben, das kann was mit signalisieren zu tun haben> muss es aber auch überhaupt nicht
Ich sehe es genau anders herum. Mit Semaphoren signalisiert man Dinge.
Das kann mit der Absicherung von Ressourcen zu tun haben, muss aber
nicht.
Aufgrund des Diskussionsverlaufs als Hilfestellung:
https://www.geeksforgeeks.org/mutex-vs-semaphore/
Ansonsten, solange der TO nicht schreibt worum es ihm konkret geht
(Stichwort Use-Case, Sprache, Beispiel-Code) ist dies eine
Freitagsdiskussion (welche ja aber auch durchaus mal Spass machen kann
;-)
cppbert schrieb:> Rolf M. schrieb:>> Mit Semaphoren signalisiert man Dinge.>> signalisieren wie Posix-Signal oder eher wie vermerken
Signalisieren in dem Sinne, dass ein Thread (in der Regel blockierend)
auf ein Ereignis wartet, dessen Eintreten durch einen anderen Thread
eben signalisiert wird.
Ein ganz typischer Anwendungsfall ist ja die Übergabe von
Arbeits-Paketen (Tasks). Für jeden Task würde man die Semaphore erhöhen,
und die Worker-Threads versuchen die Semaphore zu dekrementieren; wenn
sem_wait zurückkehrt ist also ein Task vorhanden, und er wurde
automatisch "abgebucht" (die Semaphor dekrementiert). Wenn man jetzt
alle Tasks abbrechen o.ä. will, müsste man die Semaphor zurücksetzen.
Das geht ja wie schon festgestellt nicht; daher der Vorschlag mit der
Condition Variable. Condition Variables ermöglichen es praktisch
beliebige eigene Synchronisationsmechanismen zu bauen: Über eine
beliebig modifizierbare Datenstruktur (in meinem Beispiel der
"signalCounter", als einfacher Integer), die z.B. auch eine
Liste/Schlange sein kann, kann man den Workern signalisieren was/wie
viel zu tun ist. Der Mutex stellt die Konsistenz sicher, und die
Condition Variable erlaubt es den Threads blockierend zu warten ohne
unnötig aufzuwecken.