C ++ Std Atomic

C ++ Std Atomic

Wir verwenden die „STD Atomic“, wenn wir die Atomizität der Operation in C behalten wollen++. Atomizität ist das Konzept, mit dem wir uns befassen können, wenn wir in Multithreading -Operationen/-anwendungen arbeiten, bei denen selbst die einfachen Funktionen wie das Lesen und Schreiben bei der gleichzeitigen Ausführung Probleme oder undefinierte Verhaltensweisen im Code erstellen können. Um mit einer solchen Situation umzugehen, hat C ++ die Bibliothek „std :: atomic“ definiert, die eine Konsistenz garantiert. Wenn ein Thread irgendwann schreibt, liest der andere Thread zu diesem Zeitpunkt.

Verfahren:

In diesem Artikel wird untersucht, was Atomizität ist und wie wir die Konzepte von STD Atomic verwenden können, um mit den undefinierten Verhaltensweisen in unseren Codes umzugehen. Wir werden die verschiedenen Funktionen von STD Atomic diskutieren und die verschiedenen Beispiele für STD -Atomic umsetzen. Die Funktion unter dem STD -Atomic, die wir in den verschiedenen Beispielen implementieren werden, werden wie folgt angegeben:

  • Einfachste Lesen und Schreiben von Werten
  • Veröffentlichung und Erwerben Sie die Bestellung mit Speicher (Modell)
  • Austauschmodell
  • Operation abrufen

Einfachste Lesen und Schreiben von Werten

Erstellen wir in diesem Beispiel eine Multithread -Anwendung, in der wir zwei Threads erstellen: Ein Thread zum Lesen der Werte und des anderen Threads zum Schreiben der Werte. Mit Hilfe dieses Beispiels werden wir versuchen, das Konzept der STD -Atomik zu erhalten, was das undefinierte Verhalten beim Ausführen der Multithread -Anwendungen und wie das STD -Atomic das undefinierte Verhalten eliminiert.

Dafür initiieren wir den Code einfach, indem wir zwei verschiedene Werte zwei verschiedenen Variablen vom Typ Ganzzahl zuweisen. Zunächst initialisieren wir die Variable "A" und "B" mit den Ganzzahl -Datentypen. Dann erstellen wir die Funktion, die in der Leere geschrieben ist. In dieser Funktion weisen wir die Werte sowohl „a“ und „b“ zu, e zu, e.G. 25 bzw. 20.

Dann erstellen wir die Lesefunktion. In der Read -Funktion werden die Werte von „A“ und „B“ mit dem „std :: cout“ gelesen <

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.