2012-06-20 4 views
14

Einfache Frage: garantiert das Java-Speicher-/Synchronisationsmodell atomare Zeigerschreibvorgänge? Das heißt, wenn wir konkurrierenden Threads haben:Schreiben Java-Zeiger atomar?

String shared; 

thread1() 
{ 
    shared = "a"; 
} 

thread2() 
{ 
    shared = "hello world"; 
} 

zur gleichen Zeit gestartet wird, wird shared immer garantiert null, "a" oder "hello world" sein?

+0

Hinweis: Das von der Referenz referenzierte Objekt ist möglicherweise nicht vollständig initialisiert. Die normale Implementierung von 'String' sollte in Ordnung sein, obwohl die Spezifikation für diese Art von Dingen nicht gut ist. Auch gibt es einige wenige wirklich unveränderliche Arten. Wenn Sie versuchen, sich auf so etwas zu verlassen, tun Sie wahrscheinlich etwas falsch (obwohl das kein guter Grund ist, warum nicht zu verstehen). –

Antwort

3

Es wird einer dieser drei Werte sein, ja - aber das ist undefiniert. Letzter in "gewinnt".

Sie haben nicht gefragt, aber der Vollständigkeit halber - es wird nicht "Hallo wor" oder eine Teilversion dieser Zeichenfolge sein.

4

Ja. Von section 17.7 of the JLS:

:

Schreiben und Lesen von Referenzen sind immer atomare, unabhängig davon, ob sie als 32-Bit- oder 64-Bit-Werte implementiert sind.

(Das bedeutet nicht, Sie werden immer die „neuesten“ Wert sehen, aber das ist eine andere Sache.)

+0

Als Konsequenz, warum würde die Java-Spezifikation atomare 64-Bit-Pointer-Schreibvorgänge verlangen, aber nicht die gleichen für 'lange' Schreibvorgänge? – donnyton

+0

@donnyton, Referenzen müssen atomar sein und ich kenne keine Sprache, in der Referenzen/Zeiger nicht atomar sind (wenn sie richtig ausgerichtet sind). Warum Longs nicht als atomar bezeichnet werden - das wird 32-Bit-Architekturen einschließen und atomare Schreibvorgänge könnten teurer sein, während Referenzen auf 32-Bit-Systemen nur ... gut 32 Bit breit sind. – bestsss

7

Es ist atomar.

jedoch in dem Beispiel, das Sie gab, shared ‚s-Wert necessarly nicht ein von null, a oder hello world. Es ist möglich, dass jeder Thread ohne die richtige Synchronisierung nie den Wert sehen wird, der von anderen Threads festgelegt wird. So thread 1 wird sehen a und thread 2 werden hello world gleichzeitig sehen.

Edit: Hinzugefügt Referenzen für den letzten Abschnitt für die weitere Lektüre

Die JLS, die Reihenfolge der Bedienung von verschiedenen Threads, in Chapter 17 - Threads and Locks ausgeführt erklärt. Genauer gesagt im Abschnitt 17.4.5 Happens-before Order. Auch das gut geschriebene Java Concurrency in Practice erklärt das alles gründlich.

+2

Ich glaube nicht, dass es in diesem Zusammenhang so etwas wie "zur gleichen Zeit" gibt. Mit Synchronisation werden sie nicht gleichzeitig auftreten. Ohne Synchronisation gibt es kein genau definiertes Konzept von "Zeit". –

+2

@DavidSchwartz In diesem Zusammenhang wird der Begriff "Zeit" verwendet, wie er sonst irgendwo in unserer Welt verwendet wird.Es bedeutet, dass "Thread 1" heute um 9:00 Uhr "Shared" mit dem Wert "A" und "Thread 2" mit "Hallo Welt" behandelt. Ich glaube nicht, dass es einfacher wird. – yair

+0

Die Verwendung von "Zeit" ist nicht anwendbar auf zwei nicht-unmittelbare Dinge, die keine gut definierten Starts oder Stopps haben und die nicht synchronisiert sind. Wenn Sie zum Beispiel fragen möchten, ob sich zwei Personen "zur gleichen Zeit zur Arbeit bereit machen", müssen Sie eine genaue Definition haben, wann "sich die Arbeit vorbereiten soll" - ob das Drücken der Schlummertaste am Wecker ist Teil der "Vorbereitung auf die Arbeit" oder nicht. Wenn das nicht klar definiert ist, ist auch das Konzept der "Vorbereitung zur Arbeit" nicht klar definiert. In diesem Zusammenhang "passierten sie zur gleichen Zeit?" hat keine nützliche Antwort. –