volatile (C#-Referenz)volatile (C# Reference)

Das Schlüsselwort volatile gibt an, dass ein Feld von mehreren Threads geändert werden kann, die zur gleichen Zeit ausgeführt werden.The volatile keyword indicates that a field might be modified by multiple threads that are executing at the same time. Der Compiler, das Runtimesystem und sogar die Hardware können aus Leistungsgründen die Lese- und Schreibvorgänge in den Speicherorten neu anordnen.The compiler, the runtime system, and even hardware may rearrange reads and writes to memory locations for performance reasons. Felder, die als volatile deklariert sind, sind von dieser Optimierungen nicht betroffen.Fields that are declared volatile are not subject to these optimizations. Durch Hinzufügen des volatile-Modifizierers stellen Sie sicher, dass alle Threads volatile Schreibvorgänge, die von einem anderen Thread ausgeführt werden, in der Reihenfolge ihrer Ausführung berücksichtigen.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. Es gibt keine Garantie für eine einzelne Gesamtsortierung von volatile-Schreibvorgängen aus der Sicht aller ausgeführten Threads.There is no guarantee of a single total ordering of volatile writes as seen from all threads of execution.

Das Schlüsselwort volatile kann auf Felder der folgenden Typen angewendet werden:The volatile keyword can be applied to fields of these types:

  • Verweistypen.Reference types.
  • Zeigertypen (in unsicherem Kontext).Pointer types (in an unsafe context). Beachten Sie, dass der Zeiger selbst als „volatile“ deklariert sein kann, das Objekt, auf das er zeigt aber nicht.Note that although the pointer itself can be volatile, the object that it points to cannot. Anders ausgedrückt können Sie keinen „Zeiger auf ‚volatile‘“ deklarieren.In other words, you cannot declare a "pointer to volatile."
  • Einfacher Typen wie sbyte, byte, short, ushort, int, uint, char, float und bool.Simple types such as sbyte, byte, short, ushort, int, uint, char, float, and bool.
  • Ein enum-Typ mit einem der folgenden Basistypen: byte, sbyte, short, ushort, int oder uint.An enum type with one of the following base types: byte, sbyte, short, ushort, int, or uint.
  • Generische Typparameter, die als Verweistypen bekannt sind.Generic type parameters known to be reference types.
  • IntPtr und UIntPtr.IntPtr and UIntPtr.

Andere Typen, einschließlich double und long, können nicht mit volatile markiert werden, da Lese- und Schreibvorgänge in die Felder dieser Typen nicht unbedingt atomar sind.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. Um den Multithreadzugriff auf diese Feldtypen zu schützen, verwenden Sie die Klassenmitglieder Interlocked oder schützen Sie den Zugriff mit der Anweisung lock.To protect multi-threaded access to those types of fields, use the Interlocked class members or protect access using the lock statement.

Das Schlüsselwort volatile kann nur auf Felder einer class oder struct angewendet werden.The volatile keyword can only be applied to fields of a class or struct. Lokale Variablen können nicht als volatile deklariert werden.Local variables cannot be declared volatile.

BeispielExample

Im folgenden Beispiel wird die Deklaration einer öffentlichen Feldvariable als volatile dargestellt.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;
    }
}

Im folgenden Beispiel wird veranschaulicht, wie ein Hilfs- oder Arbeitsthread erstellt wird und für das Ausführen der Verarbeitung parallel mit dem primären Thread verwendet werden kann.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. Weitere Informationen zum Multithreading finden Sie unter Verwaltetes Threading.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.
}

Wenn der volatile-Modifizierer der Deklaration von _shouldStop hinzugefügt wird, erhalten Sie immer die gleichen Ergebnisse (ähnlich dem Auszug aus dem vorhergehenden Code).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). Ohne diesen Modifizierer für das _shouldStop-Mitglied ist das Verhalten unvorhersehbar.However, without that modifier on the _shouldStop member, the behavior is unpredictable. Die DoWork-Methode kann den Mitgliederzugriff optimieren, was zum Lesen veralteter Daten führt.The DoWork method may optimize the member access, resulting in reading stale data. Aufgrund der Natur der Multithreadprogrammierung ist die Anzahl der veraltete Lesevorgänge unvorhersehbar.Because of the nature of multi-threaded programming, the number of stale reads is unpredictable. Verschiedene Programmläufe führen zu etwas unterschiedlichen Ergebnissen.Different runs of the program will produce somewhat different results.

C#-SprachspezifikationC# language specification

Weitere Informationen erhalten Sie unter C#-Sprachspezifikation.For more information, see the C# Language Specification. Die Sprachspezifikation ist die verbindliche Quelle für die Syntax und Verwendung von C#.The language specification is the definitive source for C# syntax and usage.

Siehe auchSee also