Ja, das ist notwendig. Es gibt verschiedene Methoden, mit denen Sie die Thread-Sicherheit mit verzögerter Initialisierung erreichen können:
Drakonische Synchronisation:
private static YourObject instance;
public static synchronized YourObject getInstance() {
if (instance == null) {
instance = new YourObject();
}
return instance;
}
Diese Lösung erfordert, dass jeder Thread synchronisiert wird, obwohl dies in Wirklichkeit nur die ersten sein müssen.
Überprüfen Sie die Synchronisation :
private static final Object lock = new Object();
private static volatile YourObject instance;
public static YourObject getInstance() {
YourObject r = instance;
if (r == null) {
synchronized (lock) { // While we were waiting for the lock, another
r = instance; // thread may have instantiated the object.
if (r == null) {
r = new YourObject();
instance = r;
}
}
}
return r;
}
Diese Lösung stellt sicher, dass nur die ersten Threads, die versuchen, Ihren Singleton zu erwerben, den Prozess des Erwerbs der Sperre durchlaufen müssen.
Initialisierung auf Abruf :
private static class InstanceHolder {
private static final YourObject instance = new YourObject();
}
public static YourObject getInstance() {
return InstanceHolder.instance;
}
Diese Lösung nutzt die Garantien des Java-Speichermodells für die Klasseninitialisierung, um die Thread-Sicherheit zu gewährleisten. Jede Klasse kann nur einmal geladen werden und wird nur geladen, wenn sie benötigt wird. Das heißt, das erste Mal getInstance
wird aufgerufen, InstanceHolder
geladen und instance
erstellt, und da dies von ClassLoader
s gesteuert wird , ist keine zusätzliche Synchronisation erforderlich.