volatile (odwołanie w C#)

Słowo volatile kluczowe wskazuje, że pole może być modyfikowane przez wiele wątków wykonywanych w tym samym czasie. Kompilator, system środowiska uruchomieniowego, a nawet sprzęt może zmienić rozmieszczenie odczytów i zapisów w lokalizacjach pamięci ze względu na wydajność. Zadeklarowane volatile pola są wykluczone z niektórych rodzajów optymalizacji. Nie ma gwarancji, że pojedyncza całkowita kolejność nietrwałych zapisów jest widoczna ze wszystkich wątków wykonywania. Aby uzyskać więcej informacji, zobacz klasę Volatile .

Uwaga

W systemie wieloprocesorowym operacja nietrwałego odczytu nie gwarantuje uzyskania najnowszej wartości zapisanej w tej lokalizacji pamięci przez dowolny procesor. Podobnie operacja zapisu nietrwałego nie gwarantuje, że zapisana wartość będzie natychmiast widoczna dla innych procesorów.

Słowo volatile kluczowe można zastosować do pól następujących typów:

  • Typy odwołań.
  • Typy wskaźników (w niebezpiecznym kontekście). Należy pamiętać, że chociaż sam wskaźnik może być niestabilny, obiekt, którego wskazuje, nie może. Innymi słowy, nie można zadeklarować "wskaźnika do lotnych".
  • Proste typy, takie jak sbyte, , ushortuintbyteintcharshort, , floati .bool
  • Typ enum z jednym z następujących typów bazowych: byte, , sbyteshort, ushort, intlub uint.
  • Ogólne parametry typu znane jako typy referencyjne.
  • IntPtr i UIntPtr.

Nie można oznaczyć volatile innych typów, w tym double i long, ponieważ operacje odczytu i zapisu w polach tych typów nie mogą być niepodzielne. Aby chronić dostęp wielowątkowy do tych typów pól, użyj Interlocked składowych klasy lub chroń dostęp przy użyciu instrukcji lock .

Słowo volatile kluczowe można stosować tylko do pól obiektu class lub struct. Nie można zadeklarować volatilezmiennych lokalnych .

Przykład

W poniższym przykładzie pokazano, jak zadeklarować zmienną pola publicznego jako volatile.

class VolatileTest
{
    public volatile int sharedStorage;

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

W poniższym przykładzie pokazano, jak można utworzyć pomocniczy lub wątek roboczy i użyć go do równoległego wykonywania przetwarzania z wątkiem podstawowym. Aby uzyskać więcej informacji na temat wielowątku, zobacz Managed Threading (Wątkowość zarządzana).

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 Gdy modyfikator został dodany do deklaracji_shouldStop, zawsze uzyskasz te same wyniki (podobnie jak fragment przedstawiony w poprzednim kodzie). Jednak bez tego modyfikatora elementu _shouldStop członkowskiego zachowanie jest nieprzewidywalne. Metoda DoWork może zoptymalizować dostęp do składowych, co powoduje odczytywanie nieaktualnych danych. Ze względu na charakter programowania wielowątkowego liczba nieaktualnych odczytów jest nieprzewidywalna. Różne uruchomienia programu spowodują nieco inne wyniki.

specyfikacja języka C#

Aby uzyskać więcej informacji, zobacz Specyfikacja języka C#. Specyfikacja języka jest ostatecznym źródłem informacji o składni i użyciu języka C#.

Zobacz też