8
votes

Pourquoi ce verrouillage à double vérification est-il correct? (.RAPPORTER)

J'ai beaucoup lu sur les dangers de la double verrouillage vérifiée et j'essaierais de l'écart, mais avec cela dit, je pense qu'ils font une lecture très intéressante.

Je lisais cet article de Joe Duffy À propos de la mise en œuvre du singleton avec un verrouillage double vérifié: http://www.bluebytesoftware.com/blog /Permalink ,Guid 543d89ad-8d57-4A51-B7C9-A821E3992BF6.aspx

et la solution (variante de) Il semblait proposer est-ce: xxx < / Pré>

}

Ma question est que cela n'a pas encore le danger d'écriture de la réorganisation? Spécifiquement, ces deux lignes: xxx

si ces écritures sont inversées, un autre thread peut toujours lire NULL.


2 commentaires

Veuillez poster un lien vers quelque chose sur les "dangers" de verrouillage à double coffre. Le seul danger que je connaisse consiste à ne pas la mettre en œuvre correctement.


En outre, quelle version de .NET utilisez-vous? Si vous utilisez .NET 4.0, vous pouvez utiliser paresseux pour l'initialisation paresseuse.


3 Réponses :


5
votes

Je pense que la clé est dans l'article lié ( http://msdn.microsoft.com /en-us/magazine/cc163715.aspx#ss5 ). Plus précisément que le modèle de mémoire MS-Mise en œuvre 2.0 a la propriété suivante:

Écrit ne peut pas passer au-delà des autres écrit du même fil.

Duffy mentionne que beaucoup de travail a été fait pour soutenir cela sur l'IA-64:

Nous accomplissons cela en assurant des écritures ont une sémantique «libération» sur IA-64, via l'instruction ST.REL. Un seul st.rel X garantit que toutes les autres charges et magasins menant à son exécution (dans le flux d'instructions physiques) doivent être apparues survenus sur chaque processeur logique au moins par la nouvelle valeur de X's X devient visible à un autre processeur logique. Les charges peuvent être données «Acquérir» sémantique (via l'instruction LD.ACQ), ce qui signifie que toutes les autres charges et magasins qui se produisent après qu'un LD.ACQ X ne peut sembler avoir eu lieu avant la charge.

Notez que Duffy mentionne également qu'il s'agit d'une garantie spécifique aux États membres - ce n'est pas une partie de la spécification ECMA (au moins comme de l'écriture de l'article en 2006). Donc, Mono pourrait ne pas être aussi gentil.


1 commentaires

Excellente réponse! Je m'excuse et merci de mieux avoir lu que je le fais =).



-1
votes

Selon http://msdn.microsoft.com/en-us/ Bibliothèque / EE817670.ASPX Un singleton comme xxx

est garanti pour être thread-coffre-fort

Le cadre garantit en interne la sécurité du fil sur l'initialisation de type statique. [..] Dans le cadre lui-même, plusieurs classes utilisent ce type de singleton, bien que le nom de propriété utilisé soit appelé valeur à la place. Le concept est exactement le même.


3 commentaires

Vous n'avez pas répondu à la question.


Oh je vois. Je pense que les deux lignes sont sûres (par elles-mêmes, étant gardées par une serrure appropriée sur un singleton). Cependant, la vérification volatile / non volatile de initialisée semble fragile. Est-ce ce que vous demandiez?


Votre réponse concerne les constructeurs statiques étant le fil sûr. La question concerne une méthode particulière de verrouillage à double contrôle. Sujet totalement différent. -1



2
votes

Commentaires initiaux forts>

Je ne pense pas nécessairement que l'auteur de cet article proposait réellement que cette variation du modèle de verrouillage à double vérification soit utilisée en soi. Je pense qu'il venait de souligner que c'est une variation qui pourrait être envisagée par un développeur naïf pour lutter contre le problème dans le contexte des types de valeur. P>

Types de valeur ne peut évidemment pas stocker null code> Les valeurs de sorte qu'une autre variable doit être utilisée pour signaler l'achèvement de l'initialisation. L'auteur mentionne tout cela et parle ensuite de manière confusion sur la lecture instance code> comme null code>. Vraisemblablement, l'auteur pensait à un vraiment em> développeur naïf qui a utilisé cette variation mal sur les types de valeur à une fois, puis a continué à l'appliquer, de manière incorrecte pour les types de référence. Dans le cas d'une valeur de type de valeur, un thread pourrait lire et utiliser un struct code> avec des initialisations de champ par défaut lorsque cela n'a pas été prévu. Dans le cas des types de référence, un thread pourrait lire et utiliser NULL code> instance. P>

L'utilisation de thread.volatileread code> était la proposition de l'auteur de corriger cette variation . Sans la lecture volatile, la lecture de instance code> dans l'instruction de retour pourrait soulever avant la lecture de initialisée code> comme ceci. P>

class Singleton 
{
  private static object slock = new object();
  private static Singleton instance;
  private static int initialized;
  private Singleton() {}

  public Instance {
    get {
        var local = instance;
        if (initialized == 0) {
            lock (slock) {
                if (initialized == 0) {
                    instance = new Singleton();
                    initialized = 1;
                }
            }
        }
        return local;
    }
  }
}


2 commentaires

Merci d'avoir critiqué le titre. En effet, je ne voulais pas dire que Joe proposait cela comme une technique de verrouillage double vérifiée générale, mais uniquement à la situation et à la plate-forme spécifiques qu'il a décrites. J'aurais pu mieux reformuler le titre.


@Ryaner: Oui, je n'ai jamais pensé un instant que vous avez impliqué que l'auteur préconisait cette variation. Il était évident de votre question que vous êtes bien informé de toutes les instructions de réorganisation Naunces. Je voulais juste fournir un certain contexte comment j'allais répondre à votre question.