2016-04-07 7 views
0

Entsprechend dieser post sollte die threadsichere Singleton-Klasse wie folgt aussehen. Aber ich frage mich, ob es notwendig ist volatile Schlüsselwort zu static CrunchifySingleton instance Variable hinzuzufügen. Da, wenn die Instanz erstellt und im CPU-Cache gespeichert wird und zu diesem Zeitpunkt nicht in den Hauptspeicher zurückgeschrieben wird, wird unter der Methode getInstance() ein anderer Thread aufgerufen. Wird es zu einem Inkonsistenzproblem kommen?Muss ein flüchtiges Schlüsselwort hinzugefügt werden, um threadsichere Singleton-Klassen in Java zu garantieren?

public class CrunchifySingleton { 

    private static CrunchifySingleton instance = null; 

    protected CrunchifySingleton() { 
    } 

    // Lazy Initialization 
    public static CrunchifySingleton getInstance() { 
     if (instance == null) { 
      synchronized (CrunchifySingleton.class) { 
       if (instance == null) { 
        instance = new CrunchifySingleton(); 
       } 
      } 
     } 
     return instance; 
    } 
} 
+3

Lazy initialisierte Singletons sind eine Verschwendung; Singletons im Allgemeinen sind eine schlechte Idee.Google hat Software geschrieben, um sie für die Entfernung aus ihrem Code zu identifizieren. Warum benutzt du sie? – duffymo

Antwort

0

Ja, machen flüchtige gaurantee, dass jedes Mal ein Thread den kritischen Abschnitt des Codes versucht, zuzugreifen, der Thread die Daten aus dem Speicher liest selbst und nicht aus hread Cache.

1

Der Code, wie Sie ihn zitiert haben, ist in Java gebrochen. Ja, Sie benötigen volatile und mindestens Java 5, um den doppelt überprüften Idiom Thread sicher zu machen. Außerdem sollten Sie in Ihrer verzögerten Initialisierung eine lokale Variable hinzufügen, um die Leistung zu verbessern. Lesen Sie mehr darüber hier: https://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java

+2

Ich würde niemanden DCL im Jahr 2016 direkt Der aktuelle Standard ist das [Enum Singleton] (http://keaplogik.blogspot.fi/2013/12/the-java-enum-singleton-pattern.html). – Kayaman

+0

Ich habe nicht nur gefragt, ob seine Version threadsicher ist und das war die Antwort. – Vampire

+0

Und zw. Das Enum-Singleton-Muster ist nett, aber du kannst keine faule Initialisierung machen, wenn du es brauchst, oder? – Vampire

3

Ich Echo @ Duffymo Kommentar oben: faule Singletons sind bei weitem nicht so nützlich wie sie zunächst erscheinen.

Wenn Sie jedoch unbedingt eine lazily-instanzierte Singletons verwenden müssen, die lazy holder idiom ist viel einfacher Weg, Thread-Sicherheit zu erreichen:

public final class CrunchifySingleton { 
    private static class Holder { 
    private static final CrunchifySingleton INSTANCE = new CrunchifySingleton(); 
    } 

    private CrunchifySingleton() {} 

    static CrunchifySingleton getInstance() { return Holder.INSTANCE; } 
} 

Beachten Sie auch, dass wirklich Singleton zu sein, muss die Klasse verbieten Sowohl Instanziierung als auch Unterklasse - der Konstruktor muss private sein und die Klasse muss final sein.

+0

private Konstruktor und letzte Klasse ist nicht wirklich notwendig. Privater Konstruktor ja, oder jemand kann nur instanziieren. Wenn Sie jedoch einen privaten Konstruktor haben, ist die Klasse implizit endgültig. Aber wenn man es als Finale markiert, macht es das natürlich klar. :-) – Vampire

2

Ja, wenn Ihre Singleton-Instanz nicht volatile oder auch wenn es volatile ist, aber Sie werden mit ausreichend alten JVM, gibt es keine Ordnung Garantien für die Operationen in dem die Leitung

instance = new CrunchifySingleton(); 

auf dem in Bezug zersetzt volatile speichern.

Der Compiler kann diese Operationen so umordnen, dass Ihre Instanz nicht null ist (weil Speicher zugewiesen wurde), aber immer noch nicht initialisiert ist (weil der Konstruktor noch nicht ausgeführt wurde).

Wenn Sie mehr über die versteckten Probleme rund um Double-Checked Locking erfahren möchten, speziell in Java, siehe The "Double-Checked Locking is Broken" Declaration.

Das faule Halter Idiom ist ein schönes Muster, das gut für die allgemeinen statische Feld verzögertes Laden verallgemeinert, aber wenn Sie ein sicheres und einfache Singleton Muster benötigen, würde ich empfehlen, was Josh Bloch (von Effective Java Ruhm) empfiehlt - die Java Enum Singleton:

public enum Elvis { 
    INSTANCE; 

    public void leaveTheBuilding() { ... } 
} 
0

Sie müssen volatile in diesem Fall aber eine bessere Option ist entweder ein enum zu verwenden, wenn sie staatenlos ist

enum Singleton { 
    INSTANCE; 
} 

sollte jedoch Stateful Singletons möglichst vermieden werden. Ich schlage vor, Sie versuchen, eine Instanz zu erstellen, die Sie über die Abhängigkeitsinjektion übergeben.