Frage

Ich kam in diesen Artikeln diskutieren, warum die Doppel -check Verriegelungs Paradigma wird in Java gebrochen. Ist das Paradigma gilt für .NET (insbesondere C #), wenn Variablen volatile deklariert werden?

War es hilfreich?

Lösung

Implementierung der Singleton-Muster in C # spricht über dieses Problem in der dritten Version.

Dort heißt es:

  

macht die Instanz-Variable volatile kann es, als würde explizite Gedächtnis Barriere nennt funktioniert, obwohl im letzteren Fall auch Experten nicht genau übereinstimmen können, die Barrieren erforderlich sind. Ich neige dazu, zu versuchen, Situationen zu vermeiden, in denen Experten nicht einig, was richtig und was falsch ist!

Der Autor scheint, dass eine doppelte Verriegelung zu implizieren, ist weniger wahrscheinlich, als andere Strategien zu arbeiten und somit nicht verwendet werden sollte.

Andere Tipps

Doppelte Kontrolle jetzt Sperren in Java arbeitet sowie C # (das Java-Speichermodell geändert und dies ist einer der Effekte). Allerdings müssen Sie bekommen es genau rechts. Wenn Sie durcheinander zu bringen sogar etwas, können Sie auch die Thread-Sicherheit am Ende verlieren.

Wie andere Antworten gesagt haben, wenn Sie die Umsetzung der Muster Singleton dort gibt viel bessere Möglichkeiten, es zu tun. Persönlich, wenn ich bin in einer Situation, wo ich muss wählen zwischen doppelt überprüft Verriegelung und „sperren jedes Mal,“ Code, den ich zum Sperren jedes Mal gehen würde, bis ich echte Beweise bekommen hatte, dass es einen Engpass verursacht wurde. Wenn es um Threading kommt, ein einfaches und offensichtlich richtige Muster ist viel wert.

Ich erhalte nicht, warum alle Menschen sagen, dass der Vier-Augen-Sperr schlecht Muster sind, aber nicht den Code anpassen, um es richtig zu arbeiten. Meiner Meinung nach sollte dieser Code unten gut funktionieren.

Wenn mir jemand sagen könnte, wenn dieser Code von dem in Camerons Artikeln erwähnt Problem leiden, bitte.

public sealed class Singleton {
    static Singleton instance = null;
    static readonly object padlock = new object();

    Singleton() {
    }

    public static Singleton Instance {
        get {
            if (instance != null) {
                return instance;
            }

            lock (padlock) {
                if (instance != null) {
                    return instance;
                }

                tempInstance = new Singleton();

                // initialize the object with data

                instance = tempInstance;
            }
            return instance;
        }
    }
}
  

Ich habe Sperren bekommen doppelt geprüft, indem ein boolean arbeiten (das heißt eine primitive mit der faulen Initialisierung zu vermeiden):

Die Singleton boolean Verwendung nicht funktioniert. Die Reihenfolge der Operationen zwischen verschiedenen Threads gesehen nicht gewährleistet ist, wenn Sie über eine Speicherbarriere gehen. Mit anderen Worten, wie sie aus einem zweiten Thread gesehen, created = true kann vor instance= new Singleton(); ausgeführt werden

Ich verstehe nicht ganz, warum es eine Reihe von Implementierungsmuster auf doppelt überprüft Verriegelung (anscheinend um Compiler Idiosynkrasien in verschiedenen Sprachen zu arbeiten) sind. Der Wikipedia-Artikel zu diesem Thema zeigt die naive Methode und die möglichen Wege, um das Problem zu lösen, aber keine sind so einfach wie diese (in C #):

public class Foo
{
  static Foo _singleton = null;
  static object _singletonLock = new object();

  public static Foo Singleton
  {
    get
    {
      if ( _singleton == null )
        lock ( _singletonLock )
          if ( _singleton == null )
          {
            Foo foo = new Foo();

            // Do possibly lengthy initialization,
            // but make sure the initialization
            // chain doesn't invoke Foo.Singleton.
            foo.Initialize();

            // _singleton remains null until
            // object construction is done.
            _singleton = foo;
          }
      return _singleton;
    }
  }

In Java, dann werden Sie verwenden synchronisiert () anstelle von lock (), aber es ist im Grunde die gleiche Idee. Wenn die mögliche Inkonsistenz ist, wenn das Singleton Feld zugewiesen wird, dann warum nicht nur eine lokal scoped Variable zuerst verwenden und dann das Singleton-Feld im letztmöglichen Moment zuweisen, bevor Sie den kritischen Abschnitt Verlassen? Bin ich etwas fehlt?

Es gibt das Argument @ michael-Borgwardt, dass in C # und Java statischen Feld nur einmal bei der ersten Verwendung initialisiert wird, aber , dass Verhalten ist sprachspezifisch. Und ich habe dieses Muster häufig für faule Initialisierung einer Sammlung Eigenschaft verwendet (z user.Sessions).

Ich habe Sperren bekommen doppelt geprüft, indem ein boolean arbeiten (das heißt eine primitive mit der faulen Initialisierung zu vermeiden):

private static Singleton instance;
private static boolean created;
public static Singleton getInstance() {
    if (!created) {
        synchronized (Singleton.class) {
            if (!created) {
                instance = new Singleton();
                created = true;
            }
        }
    }
    return instance;
}
scroll top