2016-04-08 11 views
0

Wie wir wissen, hat einfache Doppelprüfung Problem wegen der Befehl Umsortieren von der JVM.Java Singleton mit Double Check

Wenn ich die Instance = new MyClass(); zu den kommentierten Zeilen ersetzen. Funktioniert das?

+0

Nein. Machen Sie es einfach ['volatile'] (https://en.wikipedia.org/wiki/ Double-checked_locking # Usage_in_Java). –

+0

MyClass obj = neu MyClass(); wird eine neue Instanz zurückgeben und dann wird Instanz mit dem Objekt zugewiesen. Warum funktioniert das nicht? Ich weiß wirklich nicht warum. –

+0

Es gibt fast keinen Grund, die Sperrung zu überprüfen, selbst bei einer korrekten Implementierung mit 'volatile'. Lazy-instanziierte Singletons sollten das [Initialization on demand holder idiom] (https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom) verwenden. – Radiodef

Antwort

1

Nein, das funktioniert nicht. Betrachte Thread A und B; Thread A sieht, dass Instancenull ist und trägt den synchronisierten Block ein, um eine Instanz von MyClass zu erstellen und dem Feld Instance zuzuweisen.

Aufgrund der Regeln des Java Memory Model kann eine Neuordnung auftreten und ein teilweise initialisiertes oder sogar nicht initialisiertes Objekt von MyClass kann Instance zugewiesen werden. Jetzt geht Thread B in dieselbe GetInstance-Methode und sieht, dass Instance nicht null ist, tritt niemals auf dem gleichen Monitor wie Thread A in einen synchronisierten Block ein und gibt dann ein Objekt zurück, das nicht vollständig initialisiert ist.

Ob Sie die Initialisierung in zwei Codezeilen aufteilen oder in einer Zeile belassen, ist für dieses Problem absolut bedeutungslos: In beiden Fällen kann eine Neuordnung erfolgen. Der Java-Compiler könnte legal beide Versionen Ihres Codes mit demselben Bytecode kompilieren (obwohl der aktuelle Compiler dies nicht tut)

+0

Sie meinen, Compiler kann den Code optimieren, als Ergebnis wird kein Unterschied machen. Danke vielmals . –