volatile (C#-referens)

Nyckelordet volatile anger att ett fält kan ändras av flera trådar som körs samtidigt. Kompilatorn, körningssystemet och till och med maskinvaran kan ordna om läsningar och skrivningar till minnesplatser av prestandaskäl. Fält som deklareras volatile undantas från vissa typer av optimeringar. Det finns ingen garanti för en enda total ordning av flyktiga skrivningar som visas från alla körningstrådar. Mer information finns i Volatile klassen .

Kommentar

I ett system med flera processorer garanterar inte en flyktig läsåtgärd att det senaste värdet skrivs till den minnesplatsen av någon processor. På samma sätt garanterar inte en flyktig skrivåtgärd att värdet som skrivs omedelbart visas för andra processorer.

Nyckelordet volatile kan tillämpas på fält av följande typer:

  • Referenstyper.
  • Pekartyper (i en osäker kontext). Observera att även om själva pekaren kan vara flyktig kan det objekt som den pekar på inte göra det. Med andra ord kan du inte deklarera en "pekare till flyktig".
  • Enkla typer som , , , , , , , och floatbool. charintuintushortshortbytesbyte
  • En enum typ med någon av följande bastyper: byte, sbyte, short, ushort, int, eller uint.
  • Generiska typparametrar som är kända för att vara referenstyper.
  • IntPtr och UIntPtr.

Andra typer, inklusive double och long, kan inte markeras volatile eftersom läsningar och skrivningar till fält av dessa typer inte kan garanteras vara atomiska. Om du vill skydda åtkomst med flera trådar till dessa typer av fält använder du Interlocked klassmedlemmarna eller skyddar åtkomsten med hjälp av -instruktionen lock .

Nyckelordet volatile kan endast tillämpas på fält i en class eller struct. Lokala variabler kan inte deklareras volatile.

Exempel

I följande exempel visas hur du deklarerar en offentlig fältvariabel som volatile.

class VolatileTest
{
    public volatile int sharedStorage;

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

I följande exempel visas hur en hjälptråd eller arbetstråd kan skapas och användas för att utföra bearbetning parallellt med den primära trådens. Mer information om multitrådning finns i Hanterad trådning.

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.
}

volatile När modifieraren har lagts till i deklarationen får _shouldStop du alltid samma resultat (liknar utdraget som visas i föregående kod). Men utan den modifieraren på _shouldStop medlemmen är beteendet oförutsägbart. Metoden DoWork kan optimera medlemsåtkomsten, vilket resulterar i läsning av inaktuella data. På grund av typen av programmering med flera trådar är antalet inaktuella läsningar oförutsägbart. Olika körningar av programmet ger något olika resultat.

Språkspecifikation för C#

Mer information finns i C#-språkspecifikationen. Språkspecifikationen är den slutgiltiga källan för C#-syntax och -användning.

Se även