Programování

Osvědčené postupy pro synchronizaci vláken .Net

Synchronizace je koncept, který se používá k zabránění více vláknům v současném přístupu ke sdílenému prostředku. Můžete jej použít k zabránění tomu, aby více vláken současně vyvolalo vlastnosti nebo metody objektu. Vše, co musíte udělat, je synchronizovat blok kódu, který přistupuje ke sdílenému prostředku, nebo synchronizovat volání vlastností a členů objektu, takže v daném okamžiku může do kritické sekce vstoupit pouze jedno vlákno.

Tento článek představuje diskusi o koncepcích souvisejících se synchronizací a bezpečností podprocesů v .Net a osvědčených postupech.

Exkluzivní zámek

Exkluzivní zamykání se používá k zajištění toho, že v daném okamžiku může do kritické sekce vstoupit jedno a pouze jedno vlákno. K implementaci exkluzivních zámků ve vaší aplikaci musíte použít jednu z následujících možností.

  • Zámek - toto je syntaktická zkratka pro statické metody třídy Monitor a slouží k získání exkluzivního zámku sdíleného prostředku
  • Mutex - podobný klíčovému slovu lock kromě toho, že může fungovat napříč více procesy
  • SpinLock - slouží k získání exkluzivního zámku sdíleného prostředku tím, že se vyhne režii přepínání kontextu vlákna

K implementaci bezpečnosti vláken ve svých aplikacích můžete použít statické metody třídy Monitor nebo klíčové slovo lock. Statické členy třídy Monitor a klíčová slova zámku lze použít k zabránění souběžného přístupu ke sdílenému prostředku. Klíčové slovo lock je pouze zkratka pro implementaci synchronizace. Když však potřebujete provést složité operace ve vícevláknové aplikaci, mohou být užitečné metody Wait () a Pulse () třídy Monitor.

Následující fragment kódu ukazuje, jak můžete implementovat synchronizaci pomocí třídy Monitor.

soukromý statický objekt jen pro čtení lockObj = nový objekt ();

       static void Main (řetězec [] args)

        {

Monitor.Enter (lockObj);

                       Snaž se

            {

// Nějaký kód

            }

            Konečně

            {

Monitor.Exit (lockObj);

            }

        }

Ekvivalentní kód pomocí klíčového slova lock bude vypadat podobně jako tento:

    soukromý statický objekt jen pro čtení lockObj = nový objekt ();

static void Main (řetězec [] args)

        {  

Snaž se

            {

zámek (lockObj)

                {

// Nějaký kód

                }             

            }

Konečně

            {

// Zde můžete uvolnit jakékoli zdroje

            }

        }

Můžete využít třídu Mutex k implementaci synchronizace, která se může rozkládat napříč procesy. Všimněte si, že podobně jako v příkazu lock, zámek získaný Mutexem lze uvolnit pouze ze stejného vlákna, které bylo použito k získání zámku. Získávání a uvolňování zámků pomocí Mutexu je poměrně pomalejší než stejné pomocí příkazu lock.

Hlavní myšlenkou SpinLocku je minimalizovat náklady spojené s přepínáním kontextu mezi vlákny - pokud vlákno může nějakou dobu čekat nebo rotovat, dokud nezíská zámek na sdíleném prostředku, lze se vyhnout režii zapojené do přepínání kontextu mezi vlákny . Když kritická sekce provádí minimální množství práce, může být dobrým kandidátem na SpinLock.

Nevýhradní zámek

Chcete-li omezit souběžnost, můžete využít nevýhradní uzamčení. K implementaci nevýhradních zámků můžete použít jednu z následujících.

  • Semafor - slouží k omezení počtu vláken, která mohou mít současně přístup ke sdílenému prostředku. V podstatě se používá k současnému omezení počtu spotřebitelů pro konkrétní sdílený prostředek.
  • SemaphoreSlim - rychlá, lehká alternativa třídy Semaphore k implementaci nevýhradních zámků.
  • ReaderWriterLockSlim - třída ReaderWriterLockSlim byla zavedena v .Net Framework 3.5 jako náhrada třídy ReaderWriterLock.

Třídu ReaderWriterLockSlim můžete použít k získání neexkluzivního zámku sdíleného prostředku, který by vyžadoval časté čtení, ale občasné aktualizace. Takže místo vzájemně se vylučujícího zámku na sdíleném prostředku, který vyžaduje časté čtení a občasné aktualizace, můžete pomocí této třídy získat zámek čtení na sdíleném prostředku a exkluzivní zámek zápisu na něm.

Zablokování

Měli byste se vyhnout použití příkazu lock na typu nebo použít příkazy jako lock (this) k implementaci synchronizace ve vaší aplikaci, protože by to mohlo mít za následek zablokování. Pamatujte, že zablokování může také nastat, pokud držíte zámek získaný na sdíleném prostředku po delší dobu. Ve svých příkazech zámku byste neměli používat neměnné typy. Jako příklad byste se měli vyhnout použití řetězcového objektu jako klíče v příkazu lock. Měli byste se vyhnout použití příkazu lock na veřejném typu - je dobrým zvykem uzamknout soukromé nebo chráněné objekty, které nejsou internovány. V podstatě nastává situace zablokování, když více vláken čeká na sebe, aby uvolnily zámek na sdíleném prostředku. V tomto článku MSDN najdete další informace o zablokování.

$config[zx-auto] not found$config[zx-overlay] not found