Wie kann ein unveränderliches Objekt mit nicht endgültigen Feldern nicht sicher sein?

7

sagen wir haben das

%Vor%

Was macht diesen Thread unsicher? Im Anschluss an diese Frage .

    
NimChimpsky 17.04.2013, 14:06
quelle

4 Antworten

10

Foo ist threadsicher, sobald es sicher veröffentlicht wurde. Zum Beispiel könnte dieses Programm "unsicher" drucken (es wird wahrscheinlich keine Kombination aus Hotspot / x86 verwenden) - wenn Sie bar final machen, kann es nicht passieren:

%Vor%     
assylias 17.04.2013, 14:13
quelle
7

Aufgrund der JVM-Optimierung können Sie niemals davon ausgehen, dass Operationen in der Reihenfolge ausgeführt werden, in der sie geschrieben wurden, es sei denn, sie sind für denselben Thread von Bedeutung. Wenn Sie den Konstruktor aufrufen und dann einen Verweis auf das resultierende Objekt an einen anderen Thread übergeben, schreibt die JVM den Wert von foo.bar möglicherweise nicht, bevor sie benötigt wird, innerhalb desselben Threads .

Das bedeutet, dass in einer Multithread-Umgebung die getBar-Methode aufgerufen werden kann, bevor der Wert im Konstruktor in sie geschrieben wurde.

    
Philipp 17.04.2013 14:13
quelle
4

Wahrscheinlich hast du jetzt deine Antwort, aber um sicherzugehen, dass ich meine Erklärung auch hinzufügen wollte.

Damit ein Objekt (für Ihren Fall) Thread-sicher ist, muss es:

  • Sei unveränderlich
  • Sei sicher veröffentlicht

Unveränderlich - Sie haben es so gemacht. Es gibt keine Möglichkeit, die Leiste zu ändern, nachdem sie einmal festgelegt wurde. Ziemlich offensichtlich hier.

Sicher veröffentlicht . Wie im Beispiel ist der Code nicht sicher veröffentlicht. Da der Balken nicht endgültig ist, kann der Compiler ihn nach Belieben neu anordnen. Der Compiler könnte den Verweis auf die Foo-Instanz veröffentlichen (in den Hauptspeicher schreiben), vor den in bar schreiben. Das würde bedeuten, dass der Balken null ist. Also, zuerst wird der Verweis auf Foo in den Hauptspeicher geschrieben, dann geschieht das Schreiben in den Balken. Zwischen diesen beiden Ereignissen kann ein anderer Thread den veralteten Balken als Null ansehen.

Wenn Sie das Finale hinzufügen, garantiert das JMM Folgendes:

Die Werte der letzten Felder sind garantiert für andere Threads sichtbar, die auf das konstruierte Objekt zugreifen.

Oder das letzte Feld verhindert eine Neuanordnung. Wenn Sie diese Variable endgültig machen, wird die Thread-Sicherheit gewährleistet.

    
Eugene 24.04.2013 08:49
quelle
1

Aus dem Link , der in veröffentlicht wurde Kommentare:

%Vor%

Ein Thread kann writer() aufrufen und ein anderer Thread kann reader() aufrufen. Die if-Bedingung in reader () könnte zu true führen, aber weil y nicht endgültig ist, ist die -Objektinitialisierung möglicherweise noch nicht vollständig abgeschlossen (also wurde das Objekt noch nicht sicher veröffentlicht) und somit int j = 0 könnte passieren, da es nicht initialisiert wurde.

    
NimChimpsky 17.04.2013 14:35
quelle