Megosztás:


illékony (C# referencia)

volatile A kulcsszó használatával jelezheti, hogy egy mezőt több szál is módosíthat, amelyek egyszerre hajtanak végre. Teljesítménybeli okokból előfordulhat, hogy a fordító, a futtatókörnyezeti rendszer és még a hardver is átrendezi az olvasást és az írást a memóriahelyekre. Egy mező volatile deklarálása kizárja azt bizonyos típusú optimalizálásokból. Nincs garancia arra, hogy egyetlen teljes sorrendbe rendezze az illékony írásokat az összes végrehajtási szálon látható módon. További információ: Volatile osztály.

Figyelmeztetés

A volatile kulcsszót gyakran félreértik és visszaélnek a többszálú programozásban. A legtöbb forgatókönyvben biztonságosabb és megbízhatóbb alternatívákat használjon ahelyett volatile, hogy . A modern .NET jobb egyidejűségi eszközöket biztosít, például az Interlocked osztályt, az utasítást vagy a lock magasabb szintű szinkronizálási primitíveket. Ezek az alternatívák egyértelműbb szemantikát és erősebb garanciákat nyújtanak, mint volatilea . Fontolja meg a volatile használatát csak olyan ritka, fejlett forgatókönyvek esetén, amikor teljes mértékben tisztában van annak korlátaival, és ellenőrizte, hogy ez a megfelelő megoldás.

Megjegyzés:

A többprocesszoros rendszerekben az illékony olvasási művelet nem garantálja, hogy a legújabb értéket bármely processzor lekérte az adott memóriahelyre. Hasonlóképpen, az illékony írási művelet nem garantálja, hogy az írott érték azonnal látható legyen más processzorok számára.

A C# nyelv referenciadokumentuma a C# nyelv legújabb kiadású verzióját ismerteti. Emellett a közelgő nyelvi kiadás nyilvános előzetes verziójú funkcióinak kezdeti dokumentációját is tartalmazza.

A dokumentáció azonosítja azokat a funkciókat, amelyeket először a nyelv utolsó három verziójában vagy az aktuális nyilvános előzetes verziókban vezetnek be.

Jótanács

Ha meg szeretné tudni, hogy mikor jelent meg először egy funkció a C#-ban, tekintse meg a C# nyelvi verzióelőzményeiről szóló cikket.

Alkalmazza a kulcsszót volatile az alábbi típusú mezőkre:

  • Referenciatípusok.
  • Mutatótípusok (nem biztonságos környezetben). Bár maga a mutató volatilis lehet, az objektum, amelyre mutat, nem lehet. Más szóval nem deklarálhat "mutatót volatilisre".
  • Olyan egyszerű típusok, mint sbyte, byte, short, ushort, int, uint, char, float, és bool.
  • Az enum alábbi alaptípusok egyikével rendelkező típus: byte, , sbyte, short, ushortintvagy uint.
  • Általános típusparaméterek, amelyek referenciatípusúak.
  • IntPtr és UIntPtr.

Nem jelölhet meg más típusokat, például double és long, mivel volatile az ilyen típusú mezők olvasása és írása nem garantálható atominak. Az ilyen típusú mezőkhöz való többszálú hozzáférés védelméhez használja az Interlocked osztálytagokat, vagy az utasítással védje a lock hozzáférést.

A legtöbb többszálú forgatókönyv esetében, még a támogatott típusoknál is, inkább a Interlocked műveletek, lock utasítások vagy más szinkronizálási primitívek használatát részesítse előnyben a volatile helyett. Ezek az alternatívák kevésbé hajlamosak a finom egyidejűségi hibákra.

A kulcsszót csak egy volatile vagy structtöbb mezőre alkalmazhatjaclass. A helyi változók nem deklarálhatók volatile.

Alternatívák a volatilis memória helyett

A legtöbb esetben használja az alábbi biztonságosabb alternatívák egyikét a következő volatilehelyett:

  • Interlocked műveletek: Numerikus típusok és referencia-hozzárendelések atomi műveleteinek biztosítása. Ezek a műveletek általában gyorsabbak, és erősebb garanciákat nyújtanak, mint volatilea .
  • lock utasítás: Kölcsönös kizárást és memóriakorlátokat biztosít. Nagyobb kritikus szakaszok védelmére használható.
  • Volatile osztály: Explicit illékony olvasási és írási műveleteket biztosít a kulcsszónál volatile világosabb szemantikával.
  • Magasabb szintű szinkronizálási primitívek: például ReaderWriterLockSlim, Semaphore, vagy az System.Collections.Concurrent egyidejű gyűjteményei.

A volatile kulcsszó nem biztosít atomitást a hozzárendelésen kívüli műveletekhez. Nem akadályozza meg a versenyfeltételeket, és nem biztosít rendelési garanciát más memóriaműveletekhez. Ezek a korlátozások a legtöbb egyidejűségi forgatókönyv esetében nem megfelelőek.

Az alábbi példa bemutatja, hogyan deklarálhat nyilvános mezőváltozót volatile.

class VolatileTest
{
    public volatile int sharedStorage;

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

Az alábbi példa bemutatja, hogyan hozható létre és használható segéd- vagy feldolgozószál az elsődleges szál feldolgozásával párhuzamosan. A többszálas kezelésről további információt a Felügyelt szálkezelés című témakörben talál.

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

Amikor hozzáadja a volatile módosítót a deklarációhoz _shouldStop, mindig ugyanazokat az eredményeket kapja (hasonlóan az előző kódban látható kivonathoz). A tag módosító _shouldStop nélkül azonban a viselkedés kiszámíthatatlan. A DoWork módszer optimalizálhatja a taghozzáférést, ami elavult adatok olvasását eredményezi. A többszálú programozás természetéből adódóan az elavult olvasások száma kiszámíthatatlan. A program különböző futtatásai némileg eltérő eredményeket eredményeznek.

C# nyelvspecifikáció

További információkért lásd a C# nyelvi specifikációját. A nyelvi specifikáció a C#-szintaxis és -használat végleges forrása.

Lásd még