Ein abstrakter/Ausschnitt aus Java Concurrency In Praxis-Wie verhindert das Erstellen eines Felds als final für ein Objekt, dass ein Thread eine Nullreferenz für dasselbe Objekt erkennt?
// Unsafe publication
public Holder holder;
public void initialize(){
holder = new holder(42);
}
Zwei Dinge können mit unsachgemäß veröffentlichten Objekten schief gehen. Andere Threads könnten einen veralteten Wert für das Halterfeld sehen und somit einen null Referenzwert oder einen anderen älteren Wert sehen, obwohl ein Wert im Halter platziert wurde. Aber viel schlimmer, andere Threads konnten einen up-to-date Wert für die Halterreferenz sehen, aber veraltete Werte für den Zustand der Halter. Um die Dinge noch weniger vorhersehbar zu machen, kann ein Thread einen veralteten Wert sehen, wenn er das erste Mal ein Feld liest, und dann ein aktuelleres Wert das nächste Mal, was ist, warum assertSanity AssertionError werfen kann.
auch Objektverweis auf einem anderen Thread sichtbar wird, bedeutet nicht notwendigerweise, dass der Zustand des Objekts an den konsumierende Faden sichtbar ist
public class Holder{
private int n;
public Holder(int n) {
this.n = n;
}
public void assertSanity(){
if (n != n)
throw new AssertionError("This statement is false.");
}
}
Ofcouse, eine der Möglichkeiten, zu beheben, es wäre zu tun/machen
public volatile Holder holder;
Der Autor schlägt vor, eine andere approach-
Wenn Halter unveränderlich waren, konnte assertSanity nicht AssertionError werfen, auch wenn der Halter nicht ordnungsgemäß veröffentlicht wurde.)
public class Holder{
private final int n;
//...
}
Aber wie? Die unsichere Veröffentlichung ist immer noch da. Ich denke es ist immer noch möglich für einen Thread eine Null Referenz auf Halter zu bekommen. Bitte vorschlagen.
In Verbindung stehende http://StackOverflow.com/Questions/16107683/improper-Publication-of-JavaObjectReference und http://StackOverflow.com/A/6088679/1743880 – Tunaki