Double-Checked-Locking in Singleton
hier ist meine custom class für singleton-Muster. in diesem code verwende ich double-checked-locking wie auf der Abbildung. Als ich viele Beiträge gelesen auf irgendeiner Quelle, Sie sagen, dass double check ist nützlich, weil es verhindert, dass zwei threads gleichzeitig laufen in gleichen Zeiten zwei verschiedene Objekte.
public class DoubleCheckLocking {
public static class SearchBox {
private static volatile SearchBox searchBox;
//private constructor
private SearchBox() {}
//static method to get instance
public static SearchBox getInstance() {
if (searchBox == null) { //first time lock
synchronized (SearchBox.class) {
if (searchBox == null) { //second time lock
searchBox = new SearchBox();
}
}
}
return searchBox;
}
}
Ich verstehe immer noch nicht, obigen code so viel. Was ist das problem, wenn zwei threads zusammen führen gleichen Zeile code, die, wenn die Instanz null ist ?
if (searchBox == null) {
synchronized (SearchBox.class) {
if (searchBox == null) {
searchBox = new SearchBox();
}
}
}
Wenn die erscheinen. die beiden threads sehen-Objekt null ist. dann die beiden synchronisieren. und dann, Sie noch einmal überprüfen, und sehe Sie immer noch null. und erstellen Sie zwei verschiedene Objekte. OOOPS.
Bitte erklären für mich. Was habe ich falsch verstehen ?
Dank 🙂
InformationsquelleAutor hqt | 2013-08-07
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nicht, da Sie den Erhalt Sperre auf der
SearchBox.class
nur von einem thread betreten werden, wird der synchronisierte block zu einem Zeitpunkt. So der erste thread betritt, dann findetsearchBox
null ist, und schafft es und verlässt dann den synchronisierten block, dann den zweiten thread geben Sie den block dann feststellt, dass dersearchBox
ist nicht null, da der erste thread bereits erstellt, so dass Sie nicht erstellen Sie eine neue Instanz vonsearchBox
.Den Doppel-Karo-Muster wird verwendet, um zu vermeiden Erhalt der Sperre jedes mal, wenn der code ausgeführt wird. Wenn der Anruf nicht geschehen zusammen, dann die erste Bedingung fehl, und die Ausführung von code wird nicht ausgeführt, die Verriegelung um Ressourcen zu sparen.
danke... noch nie gesehen... geht es jetzt durch
tatsächlich ist das ist nicht gebrochen. in der jdk-1.5+ - Speicher-Modell, so dass die Referenz volatile (wie in den OP ' s code) "behebt" das double-checked-locking-Muster.
Ah, @jtahlborn so vollkommen deutlich sein, wenn die variable, die überprüft wird, ist flüchtig und wir laufen in 1.5 oder höher, diese Art von Doppel-gesperrt-Muster ist nicht kaputt? Ich persönlich bin gespannt auf diese. Wieder, ich weiß sehr wenig über dieses "problem".
Was wäre der Nachteil, wenn Methode deklariert wird, synchronisiert mit nur einer null-check?
InformationsquelleAutor Arun P Johny
Schauen wir uns diesen code:
Lassen Sie uns versuchen, vernünftig über diese. Sagen wir, wir haben zwei threads
A
undB
und lassen Sie uns davon ausgehen, dass mindestens einer von Ihnen erreicht die Linie 3 und beobachtetsearchBox == null
isttrue
. Zwei threads kann nicht beide werden in Zeile 3 zur gleichen Zeit, da dersynchronized
block. Dies ist die Schlüssel, zu verstehen, warum double-checked locking funktioniert. Es muss also der Fall, dass entwederA
oderB
durchsynchronized
ersten. Ohne Verlust der Allgemeingültigkeit, sagen, dass dieser threadA
. Dann, nach dem sehensearchBox == null
ist wahr, es wird in den Körper der Anweisung, und setzen SiesearchBox
auf eine neue Instanz vonSearchBox
. Es wird dann schließlich verlassen Sie diesynchronized
block. Jetzt wird esB
's turn zu geben: denken Sie daran,B
war blockiert warten aufA
zu beenden. Nun, wenn es in den block, es wird beobachtensearchBox
. AberA
verlassen haben, nur mitsearchBox
zu einer nicht-null
Wert. Getan.Durch die Art und Weise, in Java, der beste Weg zur Implementierung eines singleton ist die Verwendung eines single-element
enum
geben. Von Effektive Java:Es wird nicht funktionieren. Sagen thread C geht auf der Linie 1, während der thread ausgeführt wurde die Linie 4, Gewinde C, sehen möglicherweise eine teilweise errichtete Objekt. Als pro JMM, nur wenn zwei threads sperren auf demselben Objekt, das Sie garantiert, um zu sehen, gleiche version. Die sync in den Hauptspeicher passieren könnte, vor der Ausfahrt aus dem synchronisierten block.
Entsprechend passiert-vor der definition nach ein thread die Sperre, ein anderer thread erhält die Sperre, dann die letzteren können siehe die Vorherige änderung. Wenn dem so ist, ich glaube nicht, dass das volatile-Schlüsselwort ist erforderlich . Können Sie es erklären Bedeutung vorhandener genauer ?
InformationsquelleAutor jason
Diese Doppel-check lock ist nur notwendig, wenn Sie besorgt über die vielen threads, die den Aufruf des singleton gleichzeitig, oder die Kosten für die Einrichtung einer Sperre im Allgemeinen.
Sein Zweck ist zu verhindern, dass unnötige Synchronisation, dabei halten Sie Ihren code schnell in ein multi-Threading-Umgebung.
Schauen Sie sich diesen link für weitere Informationen.
Wenn Sie mit Java 1.5 oder höher, und verwenden Sie die
volatile
Schlüsselwort in Ihrem double-check gesperrt Mechanismus, es wird funktionieren. Wie Sie mit Hilfe dervolatile
Schlüsselwort, dein Beispiel ist nicht gebrochen, nach den gleichen link oben.InformationsquelleAutor William Morrison
Also im Grunde der äußeren
if
wird verwendet, um zu verhindern, dass redundante sperren - es können alle Threads wissen, dass es ist bereits ein Objekt, und Sie brauchen nicht zu sperren/zu tun. Und die innereif
ist dazu da, damit ein gleichzeitiger thread wissen, ob ein anderer hat schon das Objekt erstellt hat oder nicht.InformationsquelleAutor stan0