89 votes

Illustrer l'utilisation du mot clé volatile en C #

Je voudrais coder un petit programme qui visuellement illustre le comportement de l' volatile mot-clé. Idéalement, il devrait y avoir un programme qui effectue l'accès simultané à un non volatile champ statique et qui obtient un comportement incorrect à cause de cela.

En ajoutant le mot clé volatile dans le même programme devrait résoudre le problème.

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

Avez-vous une idée sur ce sujet? Savez-vous comment faire pour simuler un tel problème en une simple démo app? Cela dépend-il du matériel?

21voto

Craig Stuntz Points 95965

Oui, il est dépendant du matériel (il est rare de voir le problème sans plusieurs processeurs), mais il est aussi dépendant de l'implémentation. Le modèle de mémoire spécifications dans le CLR spec permis de choses qui l'implémentation Microsoft de le CLR ne le sont pas forcément. Le meilleur de la documentation que j'ai vu sur le mot clé volatile est ce blog par Joe Duffy. Notez qu'il dit la documentation MSDN est "très trompeuse."

6voto

Ray Hayes Points 9819

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

La façon la plus simple de penser, ce serait que le compilateur pourrait, si elle le voulait, inline certaines valeurs. Par le marquage de la valeur de volatile, vous dites à vous-même et le compilateur que la valeur peut changer en fait (même si le compilateur ne le pense pas). Cela signifie que le compilateur ne doit pas en ligne de valeurs, gardez cache ou lire la valeur de début (dans une tentative pour optimiser).

Ce comportement n'est pas vraiment le même mot comme en C++.

MSDN a une courte description ici. Ici est peut-être plus en profondeur un post sur les sujets de la Volatilité, l'Atomicité et de Verrouillage

4voto

Mecki Points 35351

Il est difficile de démontrer en C#, comme le code est captée par une machine virtuelle, donc sur une mise en œuvre de cette machine, il marche droit sans volatile, alors qu'il pourrait échouer sur une autre.

Wikipedia est un bon exemple de la façon de le démontrer dans C, si.

La même chose pourrait se produire en 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 le code machine qui n'a même pas vérifier plus. Si un autre thread a été la modification de la valeur, votre premier thread pourrait encore être pris dans la boucle.

Un autre exemple est Occupé Attente.

Encore une fois, cela pourrait se produire avec le C#, mais il dépend fortement de la machine virtuelle et sur le compilateur JIT (ou d'un interprète, s'il n'a pas de JIT... en théorie, je pense que MS utilise toujours un compilateur JIT et aussi Mono utilise un seul, mais vous pourriez être en mesure de le désactiver manuellement).

4voto

corlettk Points 5051

Voici ma contribution à la compréhension collective de ce comportement... C'est pas beaucoup, juste une démonstration (basé sur xkip la démo) qui montre le comportement de la volatilité et de versets non volatile (c'est à dire "normal") int valeur, côte-à-côte, dans le même programme... qui est ce que je cherchais quand j'ai trouvé ce fil de discussion.

using System;
using System.Threading;

namespace VolatileTest
{
  class VolatileTest 
  {
    private volatile int _volatileInt;
    public void Run() {
      new Thread(delegate() { Thread.Sleep(500); _volatileInt = 1; }).Start();
      while ( _volatileInt != 1 ) 
        ; // Do nothing
      Console.WriteLine("_volatileInt="+_volatileInt);
    }
  }

  class NormalTest 
  {
    private int _normalInt;
    public void Run() {
      new Thread(delegate() { Thread.Sleep(500); _normalInt = 1; }).Start();
      // NOTE: Program hangs here in Release mode only (not Debug mode).
      // See: http://stackoverflow.com/questions/133270/illustrating-usage-of-the-volatile-keyword-in-c-sharp
      // for an explanation of why. The short answer is because the
      // compiler optimisation caches _normalInt on a register, so
      // it never re-reads the value of the _normalInt variable, so
      // it never sees the modified value. Ergo: while ( true )!!!!
      while ( _normalInt != 1 ) 
        ; // Do nothing
      Console.WriteLine("_normalInt="+_normalInt);
    }
  }

  class Program
  {
    static void Main() {
#if DEBUG
      Console.WriteLine("You must run this program in Release mode to reproduce the problem!");
#endif
      new VolatileTest().Run();
      Console.WriteLine("This program will now hang!");
      new NormalTest().Run();
    }

  }
}

Il y a vraiment de super succincte les explications ci-dessus, ainsi que quelques belles références. Merci à tous de m'avoir aidé à obtenir ma tête autour de volatile (au moins assez pour savoir de ne pas s'appuyer sur volatile où mon premier instinct a été de lock ).

À bientôt, et Merci pour TOUT le poisson. Keith.


PS: je serais très intéressé par une démo de la demande initiale, qui était: "j'aimerais voir une statique volatile int se comporter correctement dans le cas où un static int se comporte mal.

J'ai essayé et échoué à ce défi. (En fait j'ai abandonné assez rapidement ;-). Dans tout ce que j'ai essayé avec statique vars ils se comporter correctement "" indépendamment de si oui ou non ils sont volatiles ... et j'aimerais une explication de POURQUOI c'est le cas, si c'est le cas... Est-ce que le compilateur ne met pas en cache les valeurs de la statique vars dans les registres (c'est à dire qu'il met en cache une référence à ce tas d'adresse à la place)?

Non ce n'est pas une nouvelle question... c'est une tentative de tsar de la communauté revenir à la question initiale.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X