volatile (référence C#)volatile (C# Reference)

Le mot clé volatile indique qu’un champ peut être modifié par plusieurs threads qui s’exécutent simultanément.The volatile keyword indicates that a field might be modified by multiple threads that are executing at the same time. Le compilateur, le système de runtime et même le matériel sont susceptibles de réorganiser les lectures et les écritures sur des emplacements de mémoire pour des raisons de performances.The compiler, the runtime system, and even hardware may rearrange reads and writes to memory locations for performance reasons. Les champs déclarés volatile ne sont pas soumis à ces optimisations.Fields that are declared volatile are not subject to these optimizations. Le fait d’ajouter le modificateur volatile permet de garantir que tous les threads observent les écritures volatiles effectuées par un autre thread dans l’ordre dans lequel elles ont été effectuées.Adding the volatile modifier ensures that all threads will observe volatile writes performed by any other thread in the order in which they were performed. Rien ne garantit que les écritures volatiles présentent un ordre total unique, tel que le voient tous les threads d’exécution.There is no guarantee of a single total ordering of volatile writes as seen from all threads of execution.

Le mot clé volatile peut être appliqué aux champs des types suivants :The volatile keyword can be applied to fields of these types:

  • Types référence.Reference types.
  • Types pointeur (dans un contexte unsafe).Pointer types (in an unsafe context). Notez que, même si le pointeur lui-même peut être volatile, l’objet sur lequel il pointe ne le peut pas.Note that although the pointer itself can be volatile, the object that it points to cannot. En d’autres termes, vous ne pouvez pas déclarer un pointeur vers un objet volatile.In other words, you cannot declare a "pointer to volatile."
  • Types simples comme sbyte, byte, short, ushort, int, uint, char, float et bool.Simple types such as sbyte, byte, short, ushort, int, uint, char, float, and bool.
  • Type enum avec l’un des types de base suivants : byte, sbyte, short, ushort, int ou uint.An enum type with one of the following base types: byte, sbyte, short, ushort, int, or uint.
  • Paramètres de type générique connus comme des types référence.Generic type parameters known to be reference types.
  • IntPtr et UIntPtr.IntPtr and UIntPtr.

Les autres types, notamment double et long, ne peuvent pas être marqués volatile, car il n’y a aucune garantie que les lectures et écritures sur des champs de ce type soient atomiques.Other types, including double and long, cannot be marked volatile because reads and writes to fields of those types cannot be guaranteed to be atomic. Pour protéger l’accès à plusieurs threads Interlocked à ces types de lock champs, utilisez les membres de la classe ou protégez l’accès à l’aide de l’instruction.To protect multi-threaded access to those types of fields, use the Interlocked class members or protect access using the lock statement.

Le mot clé volatile ne peut s’appliquer qu’aux champs d’une class ou d’un struct.The volatile keyword can only be applied to fields of a class or struct. Les variables locales ne peuvent pas être déclarées volatile.Local variables cannot be declared volatile.

 ExempleExample

L’exemple ci-dessous montre comment déclarer une variable de champ public comme volatile.The following example shows how to declare a public field variable as volatile.

class VolatileTest
{
    public volatile int sharedStorage;

    public void Test(int _i)
    {
        sharedStorage = _i;
    }
}

L’exemple suivant montre comment il est possible de créer un thread auxiliaire ou de travail et de l’utiliser pour effectuer le traitement en parallèle avec le thread principal.The following example demonstrates how an auxiliary or worker thread can be created and used to perform processing in parallel with that of the primary thread. Pour plus d'informations sur le multithreading, voir Threading managé.For more information about multithreading, see Managed Threading.

public class Worker
{
    // This method is called when the thread is started.
    public void DoWork()
    {
        bool work = false;
        while (!_shouldStop)
        {
            work = !work; // simulate some work
        }
        Console.WriteLine("Worker thread: terminating gracefully.");
    }
    public void RequestStop()
    {
        _shouldStop = true;
    }
    // Keyword volatile is used as a hint to the compiler that this data
    // member is accessed by multiple threads.
    private volatile bool _shouldStop;
}

public class WorkerThreadExample
{
    public static void Main()
    {
        // Create the worker thread object. This does not start the thread.
        Worker workerObject = new Worker();
        Thread workerThread = new Thread(workerObject.DoWork);

        // Start the worker thread.
        workerThread.Start();
        Console.WriteLine("Main thread: starting worker thread...");

        // Loop until the worker thread activates.
        while (!workerThread.IsAlive)
            ;

        // Put the main thread to sleep for 500 milliseconds to
        // allow the worker thread to do some work.
        Thread.Sleep(500);

        // Request that the worker thread stop itself.
        workerObject.RequestStop();

        // Use the Thread.Join method to block the current thread
        // until the object's thread terminates.
        workerThread.Join();
        Console.WriteLine("Main thread: worker thread has terminated.");
    }
    // Sample output:
    // Main thread: starting worker thread...
    // Worker thread: terminating gracefully.
    // Main thread: worker thread has terminated.
}

Si vous ajoutez le modificateur volatile à la déclaration de _shouldStop en place, vous obtiendrez toujours les mêmes résultats (similaires à l’extrait indiqué dans le code précédent).With the volatile modifier added to the declaration of _shouldStop in place, you'll always get the same results (similar to the excerpt shown in the preceding code). Sans ce modificateur sur le membre _shouldStop en revanche, le comportement est imprévisible.However, without that modifier on the _shouldStop member, the behavior is unpredictable. La méthode DoWork peut optimiser l’accès au membre, ce qui entraîne la lecture de données périmées.The DoWork method may optimize the member access, resulting in reading stale data. En raison de la nature de la programmation multithread, le nombre de lectures obsolètes est imprévisible.Because of the nature of multi-threaded programming, the number of stale reads is unpredictable. Différentes exécutions du programme produiront des résultats légèrement différents.Different runs of the program will produce somewhat different results.

spécification du langage C#C# language specification

Pour plus d'informations, voir la spécification du langage C#.For more information, see the C# Language Specification. La spécification du langage est la source de référence pour la syntaxe C# et son utilisation.The language specification is the definitive source for C# syntax and usage.

Voir aussiSee also