2010-04-05 14 views
41

Das Java-Speichermodell schreibt vor, dass das Schreiben einer int atomaren ist: Wenn Sie also einen Wert (bestehend aus 4 Bytes) in einem Thread schreiben und es in einem anderen lesen, werden Sie bekomme alle Bytes oder keine, aber niemals 2 neue Bytes und 2 alte Bytes oder ähnliches.Schreiben einer Referenz atomic auf 64bit VMs

Dies ist nicht garantiert für long. Hier könnte das Schreiben von 0x1122334455667788 in eine Variable, die 0 enthält, zu einem anderen Thread führen, der 0x112233440000000 oder 0x0000000055667788 lautet.

Nun schreibt die Spezifikation nicht vor, dass Objektreferenzen entweder int oder lang sein sollen. Aus Typensicherheitsgründen vermute ich, dass sie garantiert atomar geschrieben sind, aber auf einer 64-Bit-VM könnten diese Referenzen sehr gut 64-Bit-Werte (nur Speicheradressen) sein.

Jetzt sind hier meine Fragen:

  • es irgendwelche Speichermodell-Spezifikationen abdecken dies (das habe ich nicht gefunden)?
  • Sind lange Schreibvorgänge vermutlich atomar auf 64-Bit-VMs?
  • Werden VMs gezwungen, Referenzen auf 32-Bit zuzuordnen?

Grüße, Steffen

+2

@Steffen Heil: Erbsenzählerei aber beachten Sie, dass nicht alle Verweise 64 Bit intern auch auf 64-Bit-VM (aufgrund der erstaunlichen Menge an Abfall 64-Bit-Referenzen erzeugen) sind.Moderne VMs verwenden Pointer-Komprimierung/Referenz-Komprimierung genannt * "CompressedOops" *: http://wikis.sun.com/display/HotSpotInternals/CompressedOops Also ich bin nicht anderer Meinung, dass sie 64-Bit-Wert sein könnten, aber sie oft aren 't (nicht, dass es sich viel ändert zu der Antwort, die Dirk gepostet hat). – SyntaxT3rr0r

Antwort

52

Siehe JLS section 17.7: Non-atomic Treatment of double and long

Für die Zwecke der Programmiersprache Speichermodell Java, ein einzelnen Schreib zu einem nichtflüchtigen lang oder doppelten Wert als zwei behandelt separate schreibt: eins zu jeder 32-Bit-Hälfte. Dies kann zu einer Situation führen, in der ein Thread die ersten 32 Bits eines 64-Bit-Werts von eins schreibt, und die zweiten 32 Bits von einem anderen schreiben.

Schreib- und Lesevorgänge von flüchtigen langen und doppelten Werten sind immer atomar.

Schreibvorgänge und Lesevorgänge von Referenzen sind immer atomar, unabhängig davon, ob sie als 32-Bit- oder 64-Bit-Werte implementiert sind, unabhängig von .

Einige Implementierungen finden es bequemer, eine einzige Schreib Aktion auf einem 64-Bit lang oder doppelten Wert in zwei Schreibaktionen auf benachbarten 32-Bit-Werten zu teilen. Aus Effizienzgründen ist dieses Verhalten implementierungsspezifisch; eine Implementierung der Java Virtual Machine ist frei, Schreibvorgänge auf lange und doppelte Werte in zwei Teile oder atomar oder in .

Implementierungen der Java Virtual Machine werden empfohlen, möglichst keine 64-Bit-Werte zu teilen. Programmierer werden aufgefordert, freigegebene 64-Bit-Werte als flüchtig zu deklarieren oder ihre Programme korrekt zu synchronisieren, um mögliche Komplikationen zu vermeiden.

(Hervorhebung hinzugefügt)

+0

Ok, ich habe den Punkt in den Spezifikationen wieder verpasst. Mir scheint, ich bin zu müde und sollte schlafen anstatt Fragen zu stellen ... Danke für den Zeiger. (AGAIN) –

+1

Wenn "Schreibt an und liest von Referenzen sind immer atomare, unabhängig davon, ob sie als 32 oder 64-Bit-Werte implementiert sind." Warum haben wir Klasse AtomicReference (https://docs.oracle.com/javase/ 7/docs/api/java/util/gleichzeitige/atomic/AtomicReference.html)? Nur wegen der Methoden getAndSet/compareAndSet? –

+0

Nicht zerrissene Referenzwerte zu sehen ist nur ein Teil des Bildes. Die 'AtomicReference' existiert hauptsächlich für ihre Synchronisations-API (das 'compareAndSet', auf das Sie angespielt haben), @ mc.android.developer, und es gibt kein" nur "hier. Das ist eigentlich der wichtige Teil. – Dirk