2016-04-08 5 views
2

Eine atomare Bool "bereit" wird zwischen zwei Threads geteilt. Thread A führt eine Aufgabe aus, und Thread B wartet darauf, von A benachrichtigt zu werden. A wird "fertig" auf "True" setzen, wenn die Aufgabe abgeschlossen ist.C++ atomare Speicherreihenfolge vs Thread-Ereignisse wie notify()

B hat ein Warte-Prädikat, das "fertig" testet. Wenn "fertig" nach dem Aufwachen immer noch "Falsch" ist, kehrt B zum Warten zurück. (Dies verhindert, dass unerwünschte Nachläufe von Ärger)

A seine Aufgabe beendet hat, setzt „bereit“ auf True, benachrichtigt dann

B.

Frage: Wie kann ich B garantieren lesen (Last) „ready“ als wahr und nicht der ältere False?

Ich habe festgestellt, dass manchmal B liest "bereit" als False, und wacht nie auf. Was bedeutet, aus seiner Sicht kam die Benachrichtigung vor das Update, obwohl in A die Bestellung ist Update, dann notify.

HINWEISE: Ich habe zu viel über Speicherbestellung Garantien gelesen, und ich denke, ich verstehe genug über lesen und schreiben bestellen. Diese Frage beinhaltet jedoch die Bestellung von Speicher-Updates und Thread-Kommunikationsereignisse, nämlich notify. Ich kann keine klare Antwort finden, wie ich die Bestellung garantieren kann.

Siehe zB: http://www.developerfusion.com/article/138018/memory-ordering-for-atomic-operations-in-c0x/

http://bartoszmilewski.com/2008/12/01/c-atomics-and-memory-ordering/

Memory ordering behavior of std::atomic::load

Siehe auch C++ 11-Standard Abschnitt 29.3

UPDATE: Sorry für die Verwirrung, über die ist Pseudo-Code nur , von einem viel größeren Körper eingekocht und ich habe Dinge weggelassen, die nicht in das Problem suc eingreifen h als die Existenz eines Mutex auf der Zustandsvariablen. Der Arbeitscode weist die beschriebene Neuordnung des Variablenupdates auf und meldet etwa einmal alle 400 Tage Laufzeit - in der Praxis also 3-4 pro Tag. Diese ist tatsächlich passiert.

+0

Ich denke, alles, was fehlt, ist die "Rückkehr" in Ihrem Lambda. Dein Compiler sollte davor warnen; es macht das Lambda jedes Mal zu einem im Wesentlichen zufälligen Wert. – Cameron

+0

@Cameron mein Fehler, ist das oben genannte Spielzeug Pseudocode das Problem von einem viel größeren Körper, nicht wirklich funktionierenden Code. Das Ereignis, das ich beschreibe, passiert ungefähr alle ~ 400 Tage Laufzeit. – bulletsweetp

+0

Der Aufruf von 'B_cond_var.notify_one()' ist nicht in Bezug auf die Zugriffe auf 'atomic ready' angeordnet (nach meinem Verständnis sind 'atomare <> 'Instanzen geordnet nur in Bezug auf sich selbst). Ich glaube, du musst den Mutex halten, während du 'fertig 'aktualisierst, was jeden Vorteil von' bereit ', atomar zu sein, eliminieren kann. –

Antwort

1

Sie benötigen keine atomare Variable, wenn Sie sie mit einer Zustandsvariablen schützen. Zustandsvariablen erfordern jedoch Mutexe, und ich sehe Mutexe in diesem Code nicht. Ihre Lambda-Rückmeldung fehlt ebenfalls.

Korrekt verwendete Zustandsvariablen geben Ihnen das gewünschte Ergebnis.

Speicherordnung ist hier völlig irrelevant, da alle Posix-Thread-Synchronisations-Primitive volle Speicherbarrieren auferlegen.

+0

Sind Sie der Meinung, dass das notify_one einem Speicherupdate in Bezug auf die Gesamtbestellung entspricht? Wenn ja, das ist das erste Mal, dass ich das eindeutig gelesen habe. Und wenn es stimmt, würde ich gerne wissen, wie es möglich ist, dass B nicht richtig aufwacht. – bulletsweetp

+1

@bulletsweetp, Mutexe sind. Und da Zustandsvariablen immer Seite an Seite mit Mutexen verwendet werden, haben sie die gleiche Eigenschaft. Auf der tatsächlichen Frage müssen Sie den genauen Code für mich zur Verfügung stellen, um Ihnen zu erklären, warum es nicht funktioniert. Momentan ist Ihr Code nicht kompilierbar. Tatsächlich erzwingen die Cond-Vars auch die totale Ordnung selbst, wie im Standard. – SergeyA

+0

Ich werde dies als die Antwort markieren - was ich suchte, war in Ihrem Kommentar, die Tatsache, dass "Cond Vars Total Order" sowie atomare Speicher liest/schreibt. Das war, was ich im Standard oder anderswo nicht finden konnte. Übrigens zeigt diese Tatsache an, dass meine Theorie über das, was schief gelaufen ist, falsch war, und ich habe seitdem den wahren Fehler gefunden. – bulletsweetp