Aktualisiert Doppeloperation atomar

9

In Java ist das Aktualisieren der Variablen double und long möglicherweise nicht atomar, da double / long als zwei separate 32-Bit-Variablen behandelt werden.

Ссылка

Wenn ich in C ++ 32-Bit-Intel-Prozessor + Microsoft Visual C ++ - Compiler verwende, wird Doppeloperation (8 Byte) atomar aktualisiert?

Ich kann nicht viel Spezifikation zu diesem Verhalten finden.

Wenn ich "atomare Variable" sage, hier ist was ich meine:

Thread A versucht 1 in die Variable x zu schreiben. Thread B versucht, 2 in die Variable x zu schreiben.

Wir erhalten den Wert 1 oder 2 aus der Variablen x, aber keinen undefinierten Wert.

    
Cheok Yan Cheng 18.08.2009, 09:14
quelle

5 Antworten

8

Dies ist hardwarespezifisch und hängt von der Architektur ab. Für x86 und x86_64 sind 8-Byte-Schreib- oder Lesevorgänge garantiert atomar, wenn sie ausgerichtet sind. Zitat aus dem Intel Architecture Memory Ordering Whitepaper:

  

Intel 64 Speicher Bestellgarantien   das für jeden der folgenden   Speicherzugriffsanweisungen, die   konstituierende Speicheroperation erscheint   als einzigen Speicherzugriff auszuführen   unabhängig vom Speichertyp:

     
  1. Anweisungen, die ein einzelnes Byte lesen oder schreiben.

  2.   
  3. Anweisungen, die ein Wort (2 Bytes) lesen oder schreiben, dessen Adresse ist   auf einer 2-Byte-Grenze ausgerichtet.

  4.   
  5. Anweisungen, die ein Doppelwort (4 Bytes) lesen oder schreiben, dessen Adresse ist   auf einer 4-Byte-Grenze ausgerichtet.

  6.   
  7. Anweisungen, die ein Vierwort (8 Bytes) lesen oder schreiben, dessen Adresse ist   an einer 8-Byte-Grenze ausgerichtet.
  8.   

Alle gesperrten Anweisungen (implizit   gesperrt xchg Anweisung und andere   read-modify-write-Anweisungen mit a   Sperrpräfix) sind ein unteilbares und   unterbrechungsfreie Reihenfolge der Ladung (en)   gefolgt von Geschäften unabhängig von   Speichertyp und Ausrichtung.

    
hirschhornsalz 18.08.2009, 09:58
quelle
1

Man kann davon ausgehen, dass das Aktualisieren eines double niemals atomar ist, auch wenn seine Größe mit der int-Garantie identisch ist. Der Grund dafür ist, dass es einen anderen Verarbeitungspfad gibt, da es sich um einen unkritischen und teuren Datentyp handelt. Zum Beispiel erwähnen selbst Datenbarrieren normalerweise, dass sie nicht auf Fließkommadaten / Operationen im Allgemeinen anwendbar sind.

Visual C ++ wird primitiven Typen zuweisen (siehe Artikel ) und Dies sollte zwar garantieren, dass Bits während des Schreibens in den Speicher nicht verzerrt werden (8-Byte-Alignment befindet sich immer in einer 64- oder 128-Bit-Cache-Zeile). Der Rest hängt davon ab, wie die CPU nicht-atomare Daten im Cache behandelt und ob sie lesen / spülen Eine Cache-Zeile ist unterbrechbar. Also, wenn Sie durch Intel Docs für die Art von Kern graben, die Sie verwenden, und es gibt Ihnen die Garantie, dann können Sie sicher gehen.

Der Grund, warum die Java-Spezifikation so konservativ ist, ist, dass sie auf einem alten 386 und auf Corei7 genauso laufen soll. Was natürlich wahnhaft ist aber ein Versprechen ist ein Versprechen, daher verspricht es weniger :-)

Der Grund, warum ich sage, dass Sie CPU doc suchen müssen, ist, dass Ihre CPU eine alte 386 oder ähnlich sein könnte :-)) Vergessen Sie nicht, dass Ihre 8-Byte-Block auf einer 32-Bit-CPU dauert 2 "Runden" für den Zugriff, so dass Sie auf die Gnade der Mechanik des Cache-Zugriffs angewiesen sind.

Cache-Zeilenspülung, die eine viel höhere Datenkonsistenz garantiert, gilt nur für eine einigermaßen aktuelle CPU mit Intel-ian-Garantie (automatische Cache-Konsistenz).

    
ZXX 03.11.2010 01:45
quelle
-2

Ich würde nicht in irgendeiner Architektur denken, Thread / Kontextwechsel würde das Aktualisieren eines Registers auf halbem Weg unterbrechen, so dass Sie zum Beispiel 18 Bits von den 32 Bits aktualisiert erhalten, die es aktualisieren würde. Dies gilt auch für die Aktualisierung eines Speicherplatzes (vorausgesetzt, es handelt sich um eine Basiszugriffseinheit, 8,16,32,64 Bits usw.).

    
Indy9000 18.08.2009 09:32
quelle
-2

Also wurde diese Frage beantwortet? Ich habe ein einfaches Testprogramm ausgeführt, das ein Double ändert:

%Vor%

Ich habe es ohne Optimierungen (gcc -O0) kompiliert, und alle Zuweisungsoperationen werden mit einzelnen Assembleranweisungen wie fldl .LC0 und faddp %st, %st(1) durchgeführt. ( i += 84626.433 hat natürlich zwei Operationen, faddp und fstpl ).

Kann ein Thread wirklich innerhalb einer einzelnen Anweisung wie faddp ?

unterbrochen werden?     
user287010 18.03.2010 09:47
quelle
-2

Bei einem Multicore müssen Sie sich neben der Unteilbarkeit auch um die Kohärenz des Caches kümmern, damit der Thread-Wert den neuen Wert in seinem Cache sieht, wenn der Writer aktualisiert wurde.

    
excalibur 06.01.2012 13:56
quelle

Tags und Links