Était-ce utile?

La solution

mise en œuvre du modèle Singleton en C # parle sur ce problème dans la troisième version.

Il dit:

  

Faire la variable d'instance volatile peut le faire fonctionner, tout comme barrière de mémoire explicite appelle, bien que dans ce dernier cas, même les experts ne peuvent pas convenir exactement quels obstacles sont nécessaires. J'ai tendance à essayer d'éviter les situations où les experts ne sont pas d'accord ce qui est juste et ce qui ne va pas!

L'auteur semble impliquer que le double verrouillage est moins susceptible de travailler que d'autres stratégies et ne devraient donc pas être utilisé.

Autres conseils

verrouillage fonctionne maintenant de double contrôle Java ainsi que C # (le modèle de mémoire Java changé et c'est l'un des effets). Cependant, vous devez obtenir exactement à droite. Si vous gâcher les choses même un peu, vous pourriez bien finir par perdre la sécurité de fil.

Comme d'autres réponses ont dit, si vous implémentez singleton modèle il sont bien meilleures façons de le faire. Personnellement, si je suis dans une situation où je dois choisir entre verrouillage revérifié et code « verrouiller chaque fois » je vais pour bloquer chaque fois que je l'avais eu des preuves réelles qu'il était à l'origine un goulot d'étranglement. En ce qui concerne le filetage, un modèle simple et évidemment correcte vaut beaucoup.

Je ne comprends pas pourquoi tout le monde dit que le verrouillage à double contrôle est mauvais modèle, mais ne vous adaptez pas le code pour le faire fonctionner correctement. À mon avis, ce code ci-dessous devrait fonctionner très bien.

Si quelqu'un pouvait me dire si ce code souffre du problème mentionné dans l'article de Cameron, s'il vous plaît faire.

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;
        }
    }
}
  

I ai eu une double vérification de verrouillage au travail en utilisant une valeur booléenne (à savoir en utilisant une primitive d'éviter l'initialisation paresseux):

Le singleton à l'aide booléen ne fonctionne pas. L'ordre des opérations comme on le voit entre les différents threads n'est pas garantie, sauf si vous passez par une barrière de mémoire. En d'autres termes, comme on le voit d'un second fil, created = true peut être exécutée avant instance= new Singleton();

Je ne comprends pas pourquoi il y a un tas de modèles de mise en œuvre sur le verrouillage revérifié (apparemment pour contourner les idiosyncrasies du compilateur dans diverses langues). L'article de Wikipedia sur ce sujet montre la méthode naïve et les moyens possibles pour résoudre le problème, mais aucun n'est aussi simple que cela (en 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;
    }
  }

En Java, vous utiliseriez synchronisé () au lieu de verrouillage (), mais il est fondamentalement la même idée. S'il y a l'incohérence possible lorsque le champ singleton se voit assigner, alors pourquoi ne pas simplement utiliser une première variable scope localement, puis attribuer le champ singleton au dernier moment avant de quitter la section critique? Est-ce que je manque quelque chose?

Il y a l'argument @ michael-Borgwardt que C # et Java le champ statique obtient initialisé une seule fois sur la première utilisation, mais comportement est spécifique à la langue. Et je l'ai utilisé ce modèle fréquemment pour l'initialisation paresseuse d'une propriété de collection (par exemple user.Sessions).

I ai eu une double vérification de verrouillage au travail en utilisant une valeur booléenne (à savoir en utilisant une primitive d'éviter l'initialisation paresseux):

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