Sind die “Ändern”-Operatoren wie +=, |=, &= etc atomar?
Ich weiss ++ ist atomar (wenn Sie durchführen x++; in zwei verschiedenen threads “gleichzeitig” landest du immer mit x um 2 erhöht, im Gegensatz zu x=x+1 bei ausgeschalteter Optimierung.)
Was ich mich frage ist, ob variable |= constantund die Likes sind Thread-sicher oder muss ich sie mit einem Mutex schützen?
(…oder ist es CPU-abhängig? Wie ist es in diesem Fall auf ARM?)
Welcher ARM? Architektur v6 (ARM10) und höher kann atomare Operationen bereitstellen, wenn der Compiler dies unterstützt oder Sie Ihre eigene Assembly rollen. Frühere Architekturen können das nicht.
– Mike Seymour
18. März 2010 um 11:20 Uhr
gcc hat eingebaute atomare Operationen: gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/… ; Bitte beachten: “Nicht alle Operationen werden von allen Zielprozessoren unterstützt”
Abgesehen davon, dass die Sprache dies nicht garantiert, hat x86-64 einen starken Speichermodus (lädt erwerben und speichert freigeben), und selbst dort, z INC m64 da eine RMW-Operation nicht garantiert atomar ist, es sei denn, die LOCK Präfix verwendet.
– Arne Vogel
16. November 2018 um 13:43 Uhr
Sie liegen falsch. Es gibt keine Garantie dafür, dass ++ atomar ist, und es gibt auch keine Garantie für zusammengesetzte Zuweisungsoperatoren oder überhaupt für C++-Operationen.
Das heißt, das ist CPU-spezifisch. Auf Single-Core-Architekturen, die es zulassen inc [address]das ist definitiv atomar.
– SF.
18. März 2010 um 10:15 Uhr
Zumindest nicht bis C++0x: “Diese Klausel beschreibt Komponenten für feinkörnigen atomaren Zugriff. Dieser Zugriff wird über Operationen auf atomaren Objekten bereitgestellt.” [29.1/1 in the n3035 draft].
– Roger Pate
18. März 2010 um 10:15 Uhr
@SF Nein ist es nicht. Es ist Compiler-spezifisch. Nur weil eine CPU-Architektur eine Anweisung hat, bedeutet das nicht, dass der Compiler sie so verwendet, wie Sie es sich vorstellen, wenn er sie überhaupt verwendet.
– anon
18. März 2010 um 10:16 Uhr
Selbst wenn der Compiler ein atomares Inkrement erzeugen kann, kann es vom Datentyp von x abhängen, ob x++ atomar sein kann. Zum Beispiel ist auf dem Ziel von SF ein Inkrement von x, wenn x „long long“ ist, nicht atomar, und wenn es ein anderer integraler Typ wäre, könnte es möglicherweise von der spezifischen ARM-Architektur und der Datenausrichtung abhängen.
– Clifford
18. März 2010 um 12:45 Uhr
@SF: Das ist sehr spezifisch. Was ist, wenn der Compiler diese Anweisung nicht verwendet? Was ist, wenn/wenn Sie auf ein Multicore-System upgraden? Was ist mit Architekturen, die die nicht haben inc Anweisung? Im Algemeinen, ++ ist nicht atomar. Sie haben gerade einen einzigen engen Sonderfall gefunden, bei dem dies kein Problem darstellt
– jalf
18. März 2010 um 13:42 Uhr
x++ wird oft in 3 Anweisungen implementiert: Lies X in ein Register, inkrementiere es und schreibe es zurück in den Speicher.
Ihr Thread kann zwischen diesen vorbelegt werden.
Bei einigen Prozessoren können sogar einzelne Befehle nicht-atomar sein.
– Jive Dadson
19. August 2012 um 2:54 Uhr
Damit die Wertänderung über Kerne hinweg sichtbar ist, müsste ein += (zum Beispiel) den Wert laden, das Inkrement hinzufügen und dann speichern. Das bedeutet, dass die Operation ist nicht atomar.
Um die Atomarität sicherzustellen, müssten Sie die Operation entsprechend sperren.
++ kann auf Ihrem Compiler/Ihrer Plattform atomar sein, aber in den C++-Spezifikationen ist es nicht als atomar definiert.
Wenn Sie sicherstellen möchten, dass ein Wert atomar geändert wird, sollten Sie die entsprechenden Methoden verwenden, z. B. Interlocked* unter Windows.
Gleiches gilt für alle anderen Routinen. Wenn Sie atomare Operationen wünschen, sollten Sie die entsprechenden Aufrufe verwenden, nicht die Standardaufrufe.
Sockel
Nein Operator in C oder C++ ist garantiert atomar. Sie könnten auf Ihrer Plattform sein, aber Sie werden es nicht sicher wissen. Typischerweise ist die einzige Operation, die atomar ist, die Anweisung Test and Set, die normalerweise auf den meisten modernen CPUs in irgendeiner Form als Grundlage für die Implementierung von Semaphoren verfügbar ist.
JoeG
Es ist sowohl Compiler- als auch CPU-abhängig. Einige Befehlssätze bieten atomare Anweisungen für diese (auf Ints in Maschinengröße).
Es gibt jedoch keine Garantie dafür, dass Ihr Compiler diese Anweisungen verwendet und Ihren Code nicht auf nicht-threadsichere Weise optimiert. Sie müssen entweder eine Routine in Assembly schreiben oder eine Compiler-spezifische Technik (z. B. intrinsics) verwenden, die Atomarität bietet (oder eine Bibliothek verwenden, die eine dieser Techniken verwendet).
Speziell bei ARM: Die ORR/ADD/AND-Anweisungen nehmen zwei Operanden und platzieren das Ergebnis in einem Register. Jeder Operand kann dasselbe Register wie das Ergebnisregister sein, sodass sie als atomares |=, +=, &= verwendet werden können.
Natürlich wird das Ergebnis in ein Register geschrieben und der erste Operand muss auch aus einem Register stammen, also müssen Sie sicherstellen, dass die Registerladevorgänge atomar erfolgen.
Welcher ARM? Architektur v6 (ARM10) und höher kann atomare Operationen bereitstellen, wenn der Compiler dies unterstützt oder Sie Ihre eigene Assembly rollen. Frühere Architekturen können das nicht.
– Mike Seymour
18. März 2010 um 11:20 Uhr
gcc hat eingebaute atomare Operationen: gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/… ; Bitte beachten: “Nicht alle Operationen werden von allen Zielprozessoren unterstützt”
– Christoph
18. März 2010 um 11:41 Uhr
Es gibt eine Windows-API für den Zugriff auf verriegelte Variablen: msdn.microsoft.com/en-us/library/ms684122%28v=VS.85%29.aspx
– Janusz Lenar
18. März 2010 um 12:31 Uhr
Abgesehen davon, dass die Sprache dies nicht garantiert, hat x86-64 einen starken Speichermodus (lädt erwerben und speichert freigeben), und selbst dort, z
INC m64
da eine RMW-Operation nicht garantiert atomar ist, es sei denn, dieLOCK
Präfix verwendet.– Arne Vogel
16. November 2018 um 13:43 Uhr