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

C++: Speichermodell

Acquire-Release-Semantik bei den Synchronisations- und Ordnungsbedingungen

Testen Sie unsere 2017 Kurse

10 Tage kostenlos!

Jetzt testen Alle Abonnements anzeigen
Eine Release-Operation auf einer atomaren Variable synchronisiert sich mit einer Acquire-Operation auf der gleichen atomaren Variable und definiert eine Ordnungsbedingung.
07:26

Transkript

In dieser Lektion möchte ich Ihnen die Acquire-Release-Semantik genauer vorstellen. Dieses werde ich sowohl der Theorie zuerst, dann auch in der Praxis tun. Die Acquire-Release-Semantik. Die Definition der Acquire-Release-Semantik ist nicht so einfach zu verdauen, ich werde es aber dann mit ein paar Beispielen unterlegen. Also, eine release-Operation auf einer atomaren Variablen synchronisiert sich mit einer acquire-Operation auf der gleichen atomaren Variable und definiert eine Ordnungsbedingung. Zwei Eigenschaften sind an dieser Definition wichtig. Die erste Eigenschaft ist: Es geht um die gleiche atomare Variable und es wird eine Ordnungsbedingung etabliert. Was heißt das? Eine acquire-Operation ist eine Lese-Operation. Das kann eine load-Operation sein, oder auch eine test_and_set-Operation. Eine release-Operation ist eine Schreibe-Operation Das ist eine store- oder auch eine clear-Operation zum Beispiel. Jetzt geht es um die Ordnungsbedingungen. Jetzt heißt es Lese- und Schreiboperationen können nicht vor eine acquire-Operation verschoben werden. Andererseits, Lese- und Schreiboperationen können nicht hinter eine release-Operation verschoben werden. Durch die acquire- und release- Operation werden also sozusagen Barrieren etabliert. Das schaue ich mir jetzt mit Ihnen im Beispiel an, dann wird es klarer. Ich habe hier drei Threads, der erste Thread führt die Funktion "dataProducer" aus, der zweite Thread führt die Funktion "DeliveryBoy" aus, und der dritte Thread führt die Funktion "dataConsumer" aus. Was will ich hier erreichen? Ich will erreichen, dass ich im ersten Thread mySharedWork auf {1,0,3} setze, sodass ich im letzten Thread den mittleren Wert, also die Position [1] auf 2 setzen kann. Wie funktioniert das Ganze? Hier habe ich es praktisch schon skizziert. Die blauen Pfeile bezeichnen eine sog. sequence before-Beziehung oder auch, ich nenne es gerne "sourcecode order". Also, das wird vor dem, das wird vor dem und das wird vor dem ausgeführt. Die roten Pfeile bezeichnen eine sog. synchronizes with-Beziehung Das heißt, dieses "store" synchronisiert sich mit diesem "load", genauso, dieses "store" synchronisiert sich mit diesem "load". Wieso synchronisieren sich die? Ich schaue mal "dataProduced" an. Erstens findet die Operation auf der gleichen atomaren Variable statt. "dataProduced","dataProduced", "dataProduced". Zweitens hat die store-Operation hier eine release-Semantik und die Lade-Operation hier eine acquire-Semantik und dadurch erzeuge ich hier eine synchronizes with-Relation. Das ist der erste Teil dessen, was Acquire-Release-Semantik liefert. Der zweite Teil ist, dadurch ist gewährleistet, dass alles was hier davor stattfindet, zum Beispiel "mySharedWork", hier danach z. B. "dataConsumed.store" zur Verfügung steht. Das gleiche Spielchen mache ich hier nochmal. Dieses "store" synchronizes with diesem "load", wieder die gleiche atomare Variable "dataConsumed" und ich habe hier release- bzw. acquire-Semantik. Und jetzt ist es das alte transitive Spiel. sequence before etabliert eine sog. happens before-Relation, syncronizes with etabliert auch eine sog. happens before-Relation, happens before ist transitiv und jetzt kann ich einfach sagen, das geschieht vor dem, das geschieht vor dem, das geschieht vor dem, das geschieht vor dem, und das geschieht vor dem, also geschieht das vor dem hier, und genau das wollte ich zeigen. Das war die Acquire-Release-Semantik, die ich verwendet habe, um drei Threads miteinander zu synchronisieren. Jetzt zeige ich noch ein Beispiel. Das wird Ihnen dann vermutlich schon bekannter vorkommen. Was das Schöne an der Acquire-Release-Semantik ist, ist, dass die Acquire-Semantik Ihnen hilft, die höhere Threading-Schnittstelle besser zu verstehen. Hier habe ich einen kritischen Bereich, den "lock" ich hier und den "unlock" ich hier, weil hier die Variable "var" eben geschützt werden muss. Hier habe ich Pfeilchen gemalt. Eine Lock-Operation, "mut.lock" ist eine acquire-Operation. Das heißt, dass alles, was nach dem "lock" passiert, nicht vor das "lock" verschoben werden kann. Darum habe ich hier den Pfeil durchgestrichen. Eine unlock-Operation ist eine release-Operation, das heißt wiederum, dass alles, was vor dem "unlock" passiert nicht hinter das "unlock" verschoben werden darf. Sie können es sich auch so merken, was ich mir tue, Sie dürfen was aus dem kritischen Bereich nicht rausschieben, Sie dürfen aber immer was von dem nicht kritischen Bereich, hier und hier, in den kritischen Bereich reinschieben. Jetzt ist aber nicht nur ein lock eine acquire-Operation, sondern zum Beispiel auch das Warten einer Bedingungsvariable, "wait", das Starten eines Threads, eine release-Operation, ist zum Beispiel das unlocken eines mutex, genau das sehen Sie hier, aber auch die Benachrichtigung einer Bedingungsvariablen, "notify_all" oder "notify_any" und auch der join-Aufruf eines Threads, wenn also der Erzeuger-Thread auf sein Kind-Thread join aufruft. Jetzt stelle ich Ihnen noch mal den Spinlock aus der Lektion "std: :atomic_flag" vor. Jetzt habe ich die Theorie erklärt, damit der Spinlock deutlich besser, sprich performanter geschrieben werden kann. In der Lektion "std: :atomic_flag" hatte der Spinlock jeweils das Standard C++-Speichermodell. Das heißt, Sequentielle Konsistenz. In diesem Fall weiß ich aber, dass eine lock-Operation eine acquire-Operation ist und eine unlock-Operation eine release-Operation. Das heißt, es reicht vollkommen aus, für diese zwei Operationen ein deutlich schwächeres C++-Speichermodell auszuwählen, in diesem Fall die Acquire-Release-Semantik. Also, ich habe hier Acquire-Semantik und hier Release-Semantik und das Ganze bewirkt, dass dieses release sich als eine release-Operation mit der acquire hier synchronisiert, damit ist das Programm wohldefiniert, ist aber viel leichtgewichtiger synchronisiert. In dieser Lektion habe ich Ihnen die Acquire-Release-Semantik vorgestellt. Mit der Acquire-Release-Semantik können Sie atomare Operationen auf der gleichen atomaren Variable synchronisieren, indem eine Operation eine sog. Release-Semantik und die andere Operation eine sog. Acquire-Semantik hat. Gleichzeitig definieren Sie eine sog. Ordnungsbedingung, denn keine Lese- und Schreiboperation nach einer acquire-Operation darf vor eine acquire-Operation verschoben werden, keine Lese- und Schreiboperation vor einer release-Operation, darf hinter eine release-Operation verschoben werden.

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!