Was sind die verschiedenen Möglichkeiten, die wir brechen ein singleton-pattern in Java
Was sind die verschiedenen Möglichkeiten, die wir brechen ein singleton-pattern in Java.
Ich kenne einen Weg, d.h. wenn wir synchronisieren nicht die Methode im singleton -, dann können wir es schaffen, mehr als eine Instanz der Klasse. Also die Synchronisation angewendet wird. Gibt es eine Möglichkeit zu brechen singleton java-Klasse.
public class Singleton {
private static Singleton singleInstance;
private Singleton() {
}
public static Singleton getSingleInstance() {
if (singleInstance == null) {
synchronized (Singleton.class) {
if (singleInstance == null) {
singleInstance = new Singleton();
}
}
}
return singleInstance;
}
}
- eigentlich ist dieser code falsch ist, der nicht initialisierten Singleton zugeordnet werden können singleInstance, bevor Konstruktor beendet
- entfernt ee-tag, da gibt es nichts, ee-spezifische über diese Frage
- du meinst
private static Singleton singleInstance= new Singleton()
? - Nein, ich meine, dass die zugewiesenen Objekt gespeichert ist
singleInstance
vor dem Konstruktor ausgeführt wird, bedeutet dies, dass ein anderer thread Zugriff auf den nicht initialisierten singleton-was zu Fehlern führen kann - Gotcha 🙂
Du musst angemeldet sein, um einen Kommentar abzugeben.
Beginnend mit dem angegebenen code, "Double-Checked-Locking" können brocken bei einigen Umwelt,
Bei der Ausführung auf einem system mit dem Symantec-JIT, es funktioniert nicht. Insbesondere die Symantec-JIT-kompiliert
folgt (beachten Sie, dass der Symantec-JIT-mit einem Handgriff-basierten Objekt-allocation system).
Wie Sie sehen können, ist die Zuordnung zu singletons[i].Referenz durchgeführt wird, bevor der Konstruktor Singleton aufgerufen. Dies ist völlig legal im Rahmen der bestehenden Java-memory-Modell, und auch legal, in C und C++ (da keiner von Ihnen eine Speicher-Modell).
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
Abgesehen davon, dass
Serializable
Reflection
(glaube ich)*Wie lösen Sie regelbrechern?
Sie können überschreiben
readResolve()
Methode in Ihrer Klasse und Ausnahme auslösenSie können overrride
clone()
und werfenCloneNotSupported
AusnahmeBeispiel
Nachdem alle, würde ich vorschlagen, verwenden Enum als der sicherste Weg für Singleton (Seit java5 der beste Weg, es zu tun, ist die Verwendung eines enum)
if(singleInstance!=null)throw new RuntimeError();
im KonstruktorEigentlich eine sichere version ohne die Notwendigkeit für die Synchronisierung ist die Variante mit einer geschachtelten Klasse Halter:
Anderen sicheren Versionen sind:
Eifrig Initialisierung
Enum Singleton
Alle diese Versionen haben vor-und Nachteile, aber keiner von Ihnen muss explizite Synchronisierung, da Sie alle verlassen sich auf den ClassLoader und der eingebauten Thread-Sicherheit.
Wie die anderen geschrieben haben, können Sie brechen einige dieser Muster durch Deserialisierung. Lesen Sie Effektive Java von Joshua Bloch (Artikel 74 bis 78) über die Verhinderung solcher Angriffe (enum singleton-Muster ist sicher gegen solche Angriffe aus dem Feld).
Eine Möglichkeit ist die Serialisierung. Wenn Sie nicht implementieren readResolve dann Lesen, ein singleton mit ObjectInputStream.readObject() wird wieder eine neue Instanz dieser singleton.
AFAIK gibt es zwei Möglichkeiten, es könnte gebrochen werden
Mithilfe Der Reflektion
Wann gibt es custom classloadern, die mehr als ein (d.h. der parent class loader).alle singletons, die geladen werden soll durch gemeinsame übergeordnete classloader.
** Singleton-Test **
Klasse cls = Singleton.class;
Multithreading ist das größte Problem mit singletons.
Sie können vermeiden, dass durch die Synchronisierung oder Verwendung eifrig Initialisierung.
Andere Möglichkeit wäre die Verwendung von singleton, wo Sie nichts zu suchen hat. Indem Sie das singleton-Muster, das Sie anwenden können, Sie in einer Weise behindert, dass Sie Ihr Programm in späteren Entwicklung. (E. G, das erstellen einer singleton - "Spieler" in einem Spiel, weil Sie davon ausgehen, es ist ein singleplayer-Spiel. Der nächste Schritt in der Entwicklung "add co-op-Funktionalität").
Das singleton-Muster hat es Vorteile, aber verwenden Sie es nicht ohne carefull consideration.
Einen ersten Hinweis: Es wäre besser, in diesem Fall, vor allem für die Lesbarkeit, um die ganze
getSingleInstance() { }
synchronized
:Andere als das, ich glaube nicht, dass es einfach ist, den code zu knacken. Natürlich, wenn Sie hinzufügen rekursive Aufrufe, dann ist es möglich, es zu brechen, wie diese:
Singleton
's Konstruktor.Singleton
Instanz.Aber das ist das einzige, was ich denken kann, und Sie können nicht schützen Sie sich vor, dass in der
Singleton
Klasse.Synchronisierten Ansatz funktionieren wird, aber wird auch langsam jedem Zugriff auf die singleton-etwas zu schützen, das immer nur passiert, in den ersten Zugriff.
Der einfachste und sicherste Weg ist einfach zu tun, eager initialization, dass ist immer sicherer als Java garantiert, dass alle member-Variablen festgelegt werden, bevor es kann jeder auf Sie zugreifen.
Ihre aktuelle Ansatz ist tatsächlich gebrochen, auch mit Ihr synchronisiert Schleife - denn double-check-locking ist gebrochen. Sie müssen daneben die singleton-variable als
volatile
wenn du gehst zu verwenden es für double-check-locking denn ansonsten gibt es immer noch Möglichkeiten für threads Zugriff auf eine unvollständig initialisierte Objekt. Sehen http://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java für mehr details.Angenommen, Sie haben Singleton-Klasse implementiert, die als "SingletonPattern" als unten.
package com.Beispiel.Muster;
Jetzt können Sie brechen Sie die Singleton-Verhalten dieser Klasse mit den folgenden Ansatz.