C# Language volatil


Exemple

L'ajout du mot-clé volatile à un champ indique au compilateur que la valeur du champ peut être modifiée par plusieurs threads distincts. Le principal objectif du mot-clé volatile est d'empêcher les optimisations du compilateur qui supposent uniquement un accès par thread unique. L'utilisation de volatile garantit que la valeur du champ est la valeur la plus récente disponible et que la valeur n'est pas soumise à la mise en cache des valeurs non volatiles.

Il est recommandé de marquer chaque variable pouvant être utilisée par plusieurs threads comme volatile pour éviter tout comportement inattendu dû à des optimisations en arrière-plan. Considérons le bloc de code suivant:

public class Example
{
    public int x;

    public void DoStuff()
    {
        x = 5;

        // the compiler will optimize this to y = 15
        var y = x + 10;

        /* the value of x will always be the current value, but y will always be "15" */
        Debug.WriteLine("x = " + x + ", y = " + y);
    }    
}

Dans le bloc de code ci-dessus, le compilateur lit les instructions x = 5 et y = x + 10 et détermine que la valeur de y finira toujours par 15. Ainsi, il optimisera la dernière instruction comme y = 15 . Cependant, la variable x est en fait un champ public et la valeur de x peut être modifiée à l'exécution via un thread différent agissant séparément sur ce champ. Considérons maintenant ce bloc de code modifié. Notez que le champ x est maintenant déclaré comme volatile .

public class Example
{
    public volatile int x;

    public void DoStuff()
    {
        x = 5;

        // the compiler no longer optimizes this statement
        var y = x + 10;

        /* the value of x and y will always be the correct values */
        Debug.WriteLine("x = " + x + ", y = " + y);
    }    
}

Maintenant, le compilateur recherche les utilisations en lecture du champ x et s'assure que la valeur actuelle du champ est toujours extraite. Cela garantit que même si plusieurs threads lisent et écrivent dans ce champ, la valeur actuelle de x est toujours extraite.

volatile ne peut être utilisé que sur les champs de la class es ou de la struct s. Ce qui suit n'est pas valide :

public void MyMethod()
{
    volatile int x;
}

volatile ne peut être appliqué qu'aux champs des types suivants:

  • types de référence ou paramètres de type génériques connus pour être des types de référence
  • types primitifs tels que sbyte , byte , short , ushort , int , uint , char , float et bool
  • types d' sbyte basés sur byte , sbyte , short , ushort , int ou uint
  • IntPtr et UIntPtr

Remarques:

  • Le modificateur volatile est généralement utilisé pour un champ accessible par plusieurs threads sans utiliser l'instruction de verrouillage pour sérialiser l'accès.
  • Le mot clé volatile peut être appliqué aux types de référence
  • Le mot-clé volatile ne fonctionnera pas sur les primitives 64 bits sur une plate-forme 32 bits atomique. Les opérations verrouillées telles que Interlocked.Read et Interlocked.Exchange doivent toujours être utilisées pour un accès multithread sécurisé sur ces plates-formes.