Unsere Datenschutzrichtlinie wird in Kürze aktualisiert. Bitte sehen Sie sich die Vorschau an.

C++: Speichermodell

std::atomic<bool>

Testen Sie unsere 2021 Kurse

10 Tage kostenlos!

Jetzt testen Alle Abonnements anzeigen
std::atomic<bool> erlaubt, eine Bedingungsvariable auf elegante Weise zu implementieren.
07:38

Transkript

In dieser Lektion möchte ich Ihnen die atomare Variable std:: atomic<bool genauer vorstellen. Std:: atomic<bool ist ein atomarer Wahrheitswert und damit können Sie natürlich explizit den Wert auf "true" oder "false" setzen. Das Entscheidende ist natürlich in diesem Fall, das Ganze tun Sie atomar. std:: atomic<bool hat eine sehr interessante Eigenschaft: er unterstützt die Funktion compare_exchange_strong. Compare_exchange_strong ist eine sehr wichtige Funktion für atomare Variablen, weil sie es erlaubt, in einem Schritt einen Wert zu vergleichen und gegebenenfalls zu setzen, eben atomar. Die Funktion ist so wichtig, dass sie umgangssprachlich "CAS" heisst. steht für "compare and swap", und ist sozusagen Brot und Butter für lockfreie Programmierung. Jetzt schaue ich mir die Funktion ein bisschen genauer an. Sie gibt "bool' zurück, je nachdem, ob sie den Wert setzen oder nicht setzen konnte und erwartet zwei Argumente: "expected" und "desired". Wie ist das Verhalten? Wenn "atom" gleich "expected" ist, dann wird "atom" auf "desired" gesetzt. In diesem Fall gibt es dann "true" zurück. Wenn "atom" ungleich "expected" ist, wird "expected" auf "atom" gesetzt. Das hört sich ein bisschen kompliziert an, ich zeige es aber gleich in der Anwendung. Die Anwendung besteht darin, dass ich eine Bedingungsvariable implementiere oder eine Bedingungsvariable umsetze mit Hilfe von std:: atomic<bool. Hier ist die Implementierung meiner Bedingungsvariabeln, diesmal noch auf die klassische Art und Weise ohne std:: atomic<bool. Das folgt im zweiten Schritt. Eine Bedingungsvariable ist dazu da, dass zwei Threads sich über eine Benachrichtigung synchronisieren. Das heißt, es gibt einen sog. Sender, der Benachrichtungen schickt, wenn er fertig ist. Und auf der anderen Seite gibt es den Empfänger, der auf diese Benachrichtung wartet, und wenn er diese Benachrichtung bekommen hat, mit seiner Arbeit fortfährt. Man verwendet das auch gerne für sog. "Producer-Consumer" -Szenarios. Der Producer produziert was, stellt ein Ergebnis zur Verfügung, das der Consumer dann benutzt, wenn es ihm zur Verfügung steht. Hier habe ich mal den Sender dargestellt. Sie sehen, die Funktion heißt "setDataReady". Der Sender setzt die Werte des Vectors "mysharedwork" auf 103, dann benötige ich hier ein kleines "lock", damit er die nicht-atomare Variable "dataReady" auf "true" setzen kann. Und wenn er mit seiner Arbeit fertig ist, schickt er seine Benachrichtigung "notify_one". Diese Routine läuft in einem Thread ab. Im anderen Thread läuft die Routine "waitingforWork" ab. "waitingforWork" wartet mit dem gleichen (mutex_) auf die Benachrichtigung, das habe ich hier blau dargestellt, wartet, indem er den Block nutzt, und prüft, ob "dataReady" auf "true" gesetzt ist. Das ist eine Lambda-Funktion, und da die Lambda-Funktion "true" oder "false" zurückgibt, nennt man diese Lambda-Funktion auch Prädikat. Ich werde gleich noch ein paar Punkte zu "dataReady" erzählen. Es ist so, das es in C++11 notwendig ist. Und hier setzt "mysharedwork" den Wert an der Position [1] auf 2. Und das ist genau das Loch, das ich hier offen gelassen habe. Dann fehlt hier noch die Ablaufumgebung. Thread T1 führt "waitingforWork" aus, durch diese Funktion. Thread T2 führt "setDataReady" aus, durch diese Funktion. Und zum Schluss gebe ich den Vektor raus, und es kommt immer 1, 2, 3 raus. Wie funktioniert das Ganze? Sobald "setDataReady" fertig ist, schickt er hier seine Benachrichtigung über den Methodenaufruf "notify_one", und auf diese Benachrichtigung wartet der "waitingforWork" -Thread und fährt dann mit seiner Arbeit fort. Jetzt gibt es zwei relativ gemeine Phänomene bei "condition" -Variablen. Der Name dieser Phänomene ist "Lost Wake-up" und "Spurious Wake-Up". Und damit das nicht passiert, musste ich eben diese Variable "dataReady" einführen, damit dieser wartende Thread auch im richtigen Zeitpunkt aufwacht. Nochmals, "Lost Wake-Up" bedeutet: Es kann passieren, dass das Sender seine Benachrichtigung schickt und dass der Empfänger noch gar nicht in dem Zustand ist, die Benachrichtung anzunehmen. Sie können sich das vorstellen wie einen Wecker, der schellt, aber Sie sind gar nicht im Zimmer, um den Wecker zu hören. Sie warten dann ewig. Das ist das sog. "Lost Wake-Up" -Phänomen. Und dann gibt es noch das "Spurious Wake-Up" -Phänomen. Das besteht darin, dass Sie aufwachen, Sie vermeintlich glauben, der Wecker hat geschellt, aber tatsächlich war es die Katze, die an der Schlafzimmertür gekratzt hat. Diese zwei Phänomene sind der Grund, wieso Bedingungsvariablen oder "condition" -Variablen in Englisch relativ schwierig, nicht nur in C++, sondern in allen Programmiersprachen zu verwenden sind. Aus dem Grund habe ich Ihnen jetzt das gleiche Szenario nochmal implementiert, aber diesmal eben mit std:: atomic<bool. Hier habe ich "setDataReady", hier setze ich das Datum auf "ready", {1,0,3} "dataReady=true" ich verwende wieder "dataReady", aber diesmal "dataReady" eben vom Typ std:: atomic<bool. Ich initialisiere es auf "false" und hier setze ich es auf "true". Hier ist mein Thread, der wartet, "waitingforWork". Der wartet, indem er prüft, ob "dataready" auf "true" gesetzt ist. Solange es auf "false" gesetzt ist, bin ich in einer Endlosschleife und warte immer 5 Millisekunden. Wenn es auf "true" gesetzt ist, rutsche ich aus dieser Endlosschleife raus und kann den Wert an der Position[1] auf 2 setzen. Wie funktioniert das Ganze? Jetzt wird's ein bisschen mathematisch, aber so liest sich tatsächlich der Standard, wenn Sie sich die Details zum C++ Speichermodell durchlesen. Was gilt? Der obere Pfeil bedeutet "happens before". Genauso wie der untere Pfeil, der blaue. Der rote bedeutet "synchronizes with", das sind die englischen Begriffe. Was heißt das? Diese Sache hier geschieht vor dieser, auf Englisch: "happens before", weil, es steht in der Source-Code Reihenfolge eins nach dem anderen. Diese Instruktionen geschehen auch nacheinander, also "happens before". Das "happens before" dem hier, das "happens before" dem hier. Dann habe ich den roten Pfeil. Das ist eine "synchronize with" -Beziehung. Das heißt, das "dataReady=true" "synchronizes with", also synchronisiert sich mit dem "dataReady. load" hier. Und jetzt wird es mathematisch. "synchronizes with", etabliert die "happens before"-Relation oder Beziehung. Die "happens before" -Beziehung ist transitiv, und der Rest ist jetzt relativ einfach. Das "happens before" dem hier. Das "happens before" dem hier. Das "happens before" dem hier. Also passiert das hier, alles vor dem hier. Die entscheidene Schlussfolgerung ist, das "mysharedWork={1,0,3}" vor "mysharedWork[1]=2" passiert. In dieser Lektion habe ich Ihnen std:: atomic<bool genauer vorgestellt. std:: atomic<bool ist sozusagen eine atomare boolsche Variable, ein atomarer Wahrheitswert. Mit diesen atomaren Wahrheitswert können Sie bereits eine Bedingungsvariable oder auch "condition" -Variable umsetzen.

C++: Speichermodell

Verstehen und nutzen Sie die Konzepte und die zugrundeliegenden TEchnolgien des Speichermodells in C++.

1 Std. 29 min (29 Videos)
Derzeit sind keine Feedbacks vorhanden...
 
Software:
Exklusiv für Abo-Kunden
Erscheinungsdatum:24.11.2016

Dieser Online-Kurs ist als Download und als Streaming-Video verfügbar. Die gute Nachricht: Sie müssen sich nicht entscheiden - sobald Sie das Training erwerben, erhalten Sie Zugang zu beiden Optionen!

Der Download ermöglicht Ihnen die Offline-Nutzung des Trainings und bietet die Vorteile einer benutzerfreundlichen Abspielumgebung. Wenn Sie an verschiedenen Computern arbeiten, oder nicht den ganzen Kurs auf einmal herunterladen möchten, loggen Sie sich auf dieser Seite ein, um alle Videos des Trainings als Streaming-Video anzusehen.

Wir hoffen, dass Sie viel Freude und Erfolg mit diesem Video-Training haben werden. Falls Sie irgendwelche Fragen haben, zögern Sie nicht uns zu kontaktieren!