Ausgang:
Die Ausgabe dieses Beispiels zeigt das undefinierte Verhalten der Anwendung, da die Codeausgabe entweder 0 oder 10 beträgt. Dies geschah, weil die Threads gleichzeitig ausgeführt wurden und der Befehl Read bei der Ausführung des Write -Befehls möglicherweise durchgeführt wurde. Auf diese Weise haben wir ein unvollständiges Ergebnis in der Ausgabe erhalten.
Das STD-Atomer kann dieses Problem lösen und das undefinierte Verhalten in der Anwendung genau definiert machen. Um dies zu implementieren, ändern wir einfach eine kleine Änderung beim Initialisieren und Festlegen der Werte und Datentypen der definierten Variablen unter Verwendung von „STD :: Atomic“. Wir definieren die Variable "A" und "B" als die Atomvariablen durch "Std :: Atomvariablen Name". Wir ändern auch eine kleine Änderung in der Schreibfunktion, bei der wir zuvor die Werte A und B mit dem Zuweisungsoperator "=" einfach zugewiesen haben. Aber hier weisen wir die Werte mit dem „variablen Namen mit variabler Name zu. Store (value) ”Methode. Wir verwenden den variablen Namen. load () ”in der Lesefunktion. Der Rest ist der gleiche wie im vorherigen Beispiel.
Die Werte in der Ausgabe werden genau definiert gelesen und geschrieben. Und das Multithreading wird auch hier unterstützt.
Veröffentlichung und Erwerben Sie die Bestellung mit Speicher (Modell)
Das Speichermodell kann einen enormen Einfluss auf die Lese- und Schreibfunktionen des STD -Atomics haben. Das Speichermodell ist eine Standardfunktion, mit der die sequentielle Bestellkonsistenz sicherstellt. Eines der interessantesten Atommodelle ist das Veröffentlichungs- und Erwerbsmodell, bei dem wir die Veröffentlichung der Speicherbestellung für den ersten Thread und die für den zweite Thread erfasste Speicherreihenfolge speichern können, was bedeutet, dass jeder Speicher/Schreiben entweder Atom- oder Nicht-Atomic- Zuerst im ersten Thread vor dem zweiten Thread, ich.e. Belastung.
In dem Beispiel können wir also sogar die eine atomare Variable „A“ in Nicht-Atomic ändern und die zweite Variable „B“ wird atomar gehalten. In der Schreibfunktion speichern wir die nichtatomare Variable „A“ einfach, indem wir ihm einen Wert zuweisen, e.G. 30. Und wir speichern den Wert für die Atomvariable „B“ mit „B. store (value, std :: memory_order_release) ”. Gleiches gilt auch für die Read -Funktion, in der wir das „std :: cout verwenden < Ausgang:
Die Atomizität der Operation wird nach wie vor mit der Veröffentlichung und dem erfassten Speichermodell aufrechterhalten, selbst wenn wir eine nicht -atomare X-Variable hatten. Dies geschah wegen der Ys (Atomic.speichern), das sichergestellt hat, dass die aufeinanderfolgende Konsistenz gewartet wird.
Austauschmodell
Austausch bedeutet Mittel, wenn wir den Wert einer Variablen (Atomic) gegen einen anderen Wert tauschen. Im Austausch wird der Wert zuerst getauscht und dann der vorherige Wert, der vom neuen ausgetauscht wird. Sobald der Wert ausgetauscht wird, reflektiert er alle nachfolgenden Operationen zu diesem Wert. Lassen Sie uns diesen Austausch von Atomvariablen mit Hilfe eines Beispiels implementieren.
In diesem Beispiel stellen wir zunächst den globalen Atomvariablen -Foobar vor, der einen gewissen Wert entspricht, der „15“ entspricht. Im Haupt. Dann setzen wir in der für Schleife den Index von 0 auf 100 Mal ein. Anschließend ersetzen wir den Wert der Foobar -Variablen in 2 unter Verwendung von „Foobar. Tauschwert)". Danach kommen wir aus der Schleife und laden den Wert der Foobar -Variablen, um sie zu drucken. Nach dem Laden des Foobar -Werts tauschen wir jetzt seinen Wert mit 18 durch die “aus“ aus.Austausch (Wert zu ersetzen) ”Methode. Und laden Sie dann die Werte des Foobar und zeigen Sie sie mit der Druckmethode an.
Hier in diesem Beispiel muss der Thread die Werte hundertmal austauschen und der Wert von Foobar wird von 15 bis 28 ausgetauscht. Jeder Betrieb nach diesem Austausch gibt denselben Wert zurück, den in der Ausgabe zu sehen ist.
Bringen
Fetch ist die gleiche wie die Austauschfunktion, die die Werte schreibt und die zuvor abgerufenen Werte zurückgibt. Diese Operation holt den Wert, den THA vor dem Auftragen einer Operation auf sie aufbewahrt hat. Jetzt implementieren wir in diesem Beispiel das Fetch -Add und Fetch -Subtrahieren. Wir definieren eine Atomvariable mit dem vorzeichenlosen Datentyp als „Zählung“ und initialisieren die Anzahl mit Null. Dann erstellen wir zwei Funktionen. Wir führen den Zähler von Increment 1 für Add und Decrement 1 für Subtrahieren in diesen beiden Funktionen aus. Dann drucken wir diese Werte sowohl aus Fetch_add als auch von Fetch_sub -Funktionen im Hauptfunktion.
Die Funktion fetch_add gab 0 und 1 als die vorherigen Werte vor dem Inkrement zurück. Ebenso kehrte der Fetch_sub 2 und 1 als die zuvor gespeicherten Werte vor der Subtraktion oder Abnahme des One zurück.
Abschluss
In diesem Artikel haben wir die grundlegenden Operationen in „Std :: Atomic“ implementiert. Wir haben gelernt, wie wir mit den Problemen bei Multithreading -Anwendungen mithilfe des STD -Atomics umgehen können. Wir haben die verschiedenen Beispiele in C ++ für die verschiedenen Funktionen wie Fetch, Exchange, Lesen/Schreiben und Speichermodell des STD-Atomic implementiert, um die sequentielle Konsistenz und genau definierte Verhaltensweisen des Codes für Multithread-Anwendungen sicherzustellen.