web-dev-qa-db-fra.com

Illustration d'utilisation du mot clé volatile en C #

Je souhaite coder un petit programme qui illustre visuellement le comportement du mot-clé volatile. Idéalement, il devrait s'agir d'un programme qui effectue un accès simultané à un domaine statique non volatil et qui obtient un comportement incorrect à cause de cela.

L'ajout du mot clé volatile dans le même programme doit résoudre le problème.

Que quelque chose que je n'ai pas réussi à atteindre. Même essayer plusieurs fois, activant l'optimisation, etc., je reçois toujours un comportement correct sans le mot-clé "volatil".

Avez-vous une idée de ce sujet? Savez-vous comment simuler un tel problème dans une simple application de démonstration? Cela dépend-il du matériel?

87
Romain Verdier

Oui, c'est dépendant du matériel (il est peu probable de voir le problème sans plusieurs transformateurs), mais c'est aussi une mise en œuvre dépendante. Les spécifications de modèle de mémoire dans la spécification CLR permettent des choses que la mise en œuvre de Microsoft du CLR ne fait pas nécessairement. La meilleure documentation que j'ai vue sur le mot clé volatile est ce blog post de Joe Duffy . Notez qu'il dit que la documentation MSDN est "très trompeuse".

21
Craig Stuntz

Ce n'est pas vraiment une question de faute qui se passe lorsque le mot clé "volatillement" n'est pas spécifié, plus qu'une erreur pourrait se produire lorsqu'elle n'a pas été spécifiée. Généralement, vous allez savoir quand c'est le cas mieux que le compilateur!

Le moyen le plus simple de penser serait que le compilateur pouvait, s'il le voulait, sous certaines valeurs. En marquant la valeur aussi volatile, vous vous indiquez et le compilateur que la valeur peut réellement changer (même si le compilateur ne le pense pas). Cela signifie que le compilateur ne doit pas les valeurs en ligne, garder le cache ou lire la valeur tôt (dans une tentative d'optimisation).

Ce comportement n'est pas vraiment le même mot-clé que dans C++.

MSDN a une courte description ici . Voici un post peut-être plus en profondeur sur les sujets de volatilité, atomicité et verrouillage

6
Ray Hayes

Il est difficile de démontrer en C #, car le code est résumé par une machine virtuelle, donc sur une implémentation de cette machine, elle fonctionne correctement sans volatilité, alors qu'elle pourrait échouer sur un autre.

La Wikipedia a un bon exemple comment le démontrer dans C, cependant.

La même chose pourrait arriver chez C # si le compilateur JIT décide que la valeur de la variable ne peut pas changer de toute façon et crée ainsi un code de machine qui ne le contrôle plus. Si maintenant un autre fil modifiait la valeur, votre premier thread pourrait toujours être pris dans la boucle.

n autre exemple est occupé à attendre.

Encore une fois, cela pourrait se produire avec c # aussi, mais cela dépend fortement de la machine virtuelle et du compilateur JIT (ou interprète, s'il n'a pas de JIT ... En théorie, je pense que SP utilise toujours un compilateur JIT et également mono utilise un; mais vous pourriez être capable de le désactiver manuellement).

4
Mecki

Je suis tombé sur le texte suivant de Joe Albahari qui m'a beaucoup aidé.

J'ai attrapé un exemple du texte ci-dessus que j'ai modifié un peu, en créant un champ volatil statique. Lorsque vous supprimez le mot-clé volatile, le programme bloquera indéfiniment. Exécutez cet exemple dans mode .

class Program
{
    public static volatile bool complete = false;

    private static void Main()
    {           
        var t = new Thread(() =>
        {
            bool toggle = false;
            while (!complete) toggle = !toggle;
        });

        t.Start();
        Thread.Sleep(1000); //let the other thread spin up
        complete = true;
        t.Join(); // Blocks indefinitely when you remove volatile
    }
}
2
Martijn B