Frage

Löst dieser Code das doppelt überprüfte Sperrproblem in Java?

public class DBAccessService() {
    private static DBAccessService INSTANCE;  

    private DBAccessService() {}

    public static DBAccessService getInstance() {
        if (INSTANCE != null) {
            return INSTANCE;
        }
        return createInstance();
    }

    private static synchronized DBAccessService createInstance() {
        if (INSTANCE != null) {
            return INSTANCE;
        }
        DBAccessService instance = new DBAccessService();
        INSTANCE = instance;

        return INSTANCE;
    }
}

Es sind 2 Aspekte zu beachten:

  1. getInstance() is nicht synchronisiert, sodass nach der Initialisierung der INSTANZ keine Kosten für die Synchronisierung anfallen
  2. createInstance() ist synchronisiert

Also, die Frage ist:hat dieser Code irgendwelche Probleme?Ist es legal und immer thread-sicher?

War es hilfreich?

Lösung

Um diese spezielle Frage zu lösen Java-Parallelität in der Praxis (geschrieben vom Team, der im Wesentlichen die Java.Util geschrieben hat .concurrent Library) empfiehlt den faule Initialisierungshalterklasse IDIOM (in meiner Kopie, Auflistung 16.6, nicht 16,7) generasacodicetagpre.

Dies ist immer legal und fadensicher. Ich bin kein Experte, also kann ich nicht sagen, dass das besser ist als dein Code. Angesichts dessen, dass es das von Doug Lea und Joshua-Bloch empfohlene Muster ist, würde ich es immer über Code verwenden, oder ich habe erfunden, da es so einfach ist, Fehler zu machen (wie durch die Anzahl der falschen Antworten auf diese Frage gezeigt) ).

im Zusammenhang mit dem volatilen Thema, das sie sagen:

anschließende Änderungen in der JMM (Java 5.0 und höher) haben DCL-Funktion aktiviert, wenn die Ressource volatilisiert wird ... Die faule Initialisierungshalter-IDIOM bietet jedoch die gleichen Vorteile und ist einfacher zu verstehen.

Andere Tipps

Sie müssen deklarieren INSTANCE als volatile damit es funktioniert:

private static volatile DBAccessService INSTANCE;

Beachten Sie, dass es nur mit Java 5 und höher funktioniert.Sehen Die Deklaration "Doppelt geprüfte Verriegelung ist defekt".

In diesem Artikel wird es behauptet, dass "doppeltes"Die geprüfte Protokollierung "ist kein Problem, wenn Sie eine separate Singleton-Klasse verwenden: generasacodicetagpre.

es hat den gleichen Vorteil: Das Feld wird nicht instanziiert, bevor er das erste Mal referenziert wird.

Wie bereits erwähnt, wenn Sie aufbewahren möchten, wenn Sie es halten möchten, dass er generakodicetagcode fehlt, falls Sie nur JDK>= 5. ansprechen

Es ist nicht faden/ a>.Es gibt keine Garantie, dass ein Thread die vollständig initialisierte Instanz von dbaccessservice sehen wird.Warum nicht einfach mit einfachem verwenden? generasacodicetagpre.

Sieht gut aus.Wenn zwei Threads getInstance() aufrufen und die INSTANZ nicht initialisiert ist, kann nur ein Thread mit CreateInstance() fortfahren, und der zweite sieht bereits, dass die Instanz nicht null ist.

Das einzige ist volatile stichwort zum Beispiel.Andernfalls kann Java es zwischenspeichern.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top