Přehled primitiv synchronizace

.NET poskytuje řadu typů, které můžete použít k synchronizaci přístupu ke sdílenému prostředku nebo koordinaci interakce vlákna.

Důležité

K ochraně přístupu ke sdílenému prostředku použijte stejnou primitivní instanci synchronizace. Pokud k ochraně stejného prostředku použijete různé primitivní instance synchronizace, obcházíte ochranu poskytnutou primitivem synchronizace.

WaitHandle – třída a jednoduché typy synchronizace

Několik primitiv synchronizace rozhraní .NET je odvozeno z System.Threading.WaitHandle třídy, která zapouzdřuje nativní synchronizační popisovač operačního systému a používá mechanismus signalizace pro interakci s vlákny. Mezi tyto třídy patří:

  • System.Threading.Mutex, který uděluje výhradní přístup ke sdílenému prostředku. Stav mutexu je signalován, pokud ho žádné vlákno nevlastní.
  • System.Threading.Semaphore, což omezuje počet vláken, která mohou současně přistupovat ke sdílenému prostředku nebo fondu prostředků. Stav semaforu je nastaven tak, aby signalizoval, když je jeho počet větší než nula a nepřiřazeno, pokud je jeho počet nula.
  • System.Threading.EventWaitHandle, který představuje událost synchronizace vláken a může být buď v signalifikovaném nebo nepodepsaném stavu.
  • System.Threading.AutoResetEvent, který je odvozen od EventWaitHandle a při signálu, se po uvolnění jednoho čekajícího vlákna automaticky obnoví na nepodepsaný stav.
  • System.Threading.ManualResetEvent, který je odvozen od EventWaitHandle a při signálu zůstává v signalizačním stavu, dokud Reset se metoda nevolá.

V rozhraní .NET Framework lze tyto WaitHandleSystem.MarshalByRefObjecttypy použít k synchronizaci aktivit vláken napříč hranicemi domény aplikace.

V rozhraní .NET Framework, .NET Core a .NET 5+ mohou některé z těchto typů představovat pojmenované popisovače synchronizace systému, které jsou viditelné v celém operačním systému a lze je použít pro synchronizaci mezi procesy:

Další informace najdete v referenčních informacích k WaitHandle rozhraní API.

Zjednodušené typy synchronizace nespoléhá na podkladové popisovače operačního systému a obvykle poskytují lepší výkon. Nelze je však použít pro synchronizaci mezi procesy. Tyto typy použijte pro synchronizaci vláken v jedné aplikaci.

Některé z těchto typů jsou alternativy k typům odvozených z WaitHandle. Jedná se například SemaphoreSlim o odlehčenou alternativu k Semaphore.

Synchronizace přístupu ke sdílenému prostředku

.NET poskytuje řadu primitiv synchronizace pro řízení přístupu ke sdílenému prostředku několika vlákny.

Monitor – třída

Třída System.Threading.Monitor uděluje vzájemně se vylučující přístup ke sdílenému prostředku získáním nebo uvolněním zámku objektu, který identifikuje prostředek. Zatímco se zámek drží, vlákno, které zámek obsahuje, může zámek znovu získat a uvolnit. Jakékoli jiné vlákno je blokováno získání zámku a Monitor.Enter metoda čeká, až se zámek uvolní. Metoda Enter získá uvolněný zámek. Metodu Monitor.TryEnter můžete použít také k určení doby, po kterou se vlákno pokusí získat zámek. Monitor Protože třída má spřažení vláken, vlákno, které získal zámek musí uvolnit zámek voláním Monitor.Exit metody.

Můžete koordinovat interakci vláken, které získávají zámek na stejném objektu Monitor.Waitpomocí , Monitor.Pulsea Monitor.PulseAll metody.

Další informace najdete v referenčních informacích k Monitor rozhraní API.

Poznámka:

Příkaz lock použijte v jazyce C# a příkaz SyncLock v jazyce Visual Basic k synchronizaci přístupu ke sdílenému prostředku místo přímého použití Monitor třídy. Tyto příkazy se implementují pomocí Enter metod a Exittry…finally bloku, aby se zajistilo, že se získaný zámek vždy uvolní.

Mutex – třída

Třída System.Threading.Mutex , například Monitor, uděluje výhradní přístup ke sdílenému prostředku. Použijte jeden z Mutex.WaitOne přetížení metody k vyžádání vlastnictví mutex. Stejně jako Monitor, Mutex má spřažení vlákna a vlákno, které získal mutex musí ho uvolnit voláním Mutex.ReleaseMutex metody.

Na rozdíl od Monitortřídy Mutex lze použít pro synchronizaci mezi procesy. K tomu použijte pojmenovaný mutex, který je viditelný v celém operačním systému. Pokud chcete vytvořit pojmenovanou instanci mutex, použijte konstruktor Mutex, který určuje název. Můžete také volat metodu Mutex.OpenExisting pro otevření existující pojmenované systémové mutex.

Další informace najdete v článku o mutexech a referenčních informacích k Mutex rozhraní API.

Struktura SpinLock

Struktura System.Threading.SpinLock , například Monitor, uděluje výhradní přístup ke sdílenému prostředku na základě dostupnosti zámku. Když SpinLock se pokusí získat zámek, který není k dispozici, čeká ve smyčce a opakovaně kontroluje, dokud zámek nebude dostupný.

Další informace o výhodách a nevýhodách použití zámku číselníku najdete v článku SpinLock a referenční informace k SpinLock rozhraní API.

ReaderWriterLockSlim – třída

Třída System.Threading.ReaderWriterLockSlim uděluje výhradní přístup ke sdílenému prostředku pro zápis a umožňuje více vláken přístup k prostředku současně pro čtení. Možná budete chtít použít ReaderWriterLockSlim k synchronizaci přístupu ke sdílené datové struktuře, která podporuje operace čtení bezpečné pro přístup z více vláken, ale vyžaduje výhradní přístup k provedení operace zápisu. Když vlákno požádá o výhradní přístup (například voláním ReaderWriterLockSlim.EnterWriteLock metody), další čtenář a zapisovač požadavky blokují, dokud všechny stávající čtenáři zámek nezavřely a zapisovač zámek vstoupil a ukončil.

Další informace najdete v referenčních informacích k ReaderWriterLockSlim rozhraní API.

Semaphore a SemaphoreSlim – třídy

System.Threading.SemaphoreSlim Třídy System.Threading.Semaphore omezují počet vláken, která mohou současně přistupovat ke sdílenému prostředku nebo fondu prostředků. Další vlákna, která požadují prostředek, čekají, dokud žádné vlákno uvolní semaphore. Vzhledem k tomu, že semaphore nemá spřažení vláken, může vlákno získat semafor a jiný ho může uvolnit.

SemaphoreSlim je zjednodušená alternativa Semaphore k synchronizaci pouze v rámci jedné hranice procesu.

Ve Windows můžete použít Semaphore pro synchronizaci mezi procesy. K tomu vytvořte Semaphore instanci, která představuje pojmenovaný systémový semaphore pomocí jednoho z konstruktorů Semaphore, které určují název nebo metodu Semaphore.OpenExisting . SemaphoreSlim nepodporuje pojmenované systémové semafory.

Další informace najdete v článku Semaphore a SemaphoreSlim a referenční informace k Semaphore rozhraní API.SemaphoreSlim

Interakce s vlákny nebo signalizace

Interakce vlákna (nebo signalizace vlákna) znamená, že vlákno musí čekat na oznámení nebo signál z jednoho nebo více vláken, aby bylo možné pokračovat. Pokud například vlákno A volá metodu Thread.Join vlákna B, vlákno A je blokováno, dokud vlákno B se dokončí. Primitivy synchronizace popsané v předchozí části poskytují jiný mechanismus pro signalizaci: uvolněním zámku vlákno oznámí jinému vláknu, že může pokračovat získáním zámku.

Tato část popisuje další konstruktory signalizace poskytované rozhraním .NET.

Třídy EventWaitHandle, AutoResetEvent, ManualResetEvent a ManualResetEventSlim

Třída System.Threading.EventWaitHandle představuje událost synchronizace vláken.

Událost synchronizace může být buď v nepodepsaném nebo signalizačním stavu. Pokud je stav události nepodepsaný, vlákno, které volá přetížení události WaitOne , je blokováno, dokud se událost neoznačí. Metoda EventWaitHandle.Set nastaví stav události, která se signalizovala.

Chování EventWaitHandle signálu závisí na jeho režimu resetování:

Ve Windows můžete použít EventWaitHandle pro synchronizaci mezi procesy. K tomu vytvořte EventWaitHandle instanci, která představuje pojmenovanou událost synchronizace systému pomocí jednoho z konstruktorů EventWaitHandle, které určují název nebo metodu EventWaitHandle.OpenExisting .

Další informace naleznete v článku EventWaitHandle . Referenční informace k rozhraní API naleznete v tématu EventWaitHandle, AutoResetEvent, ManualResetEventa ManualResetEventSlim.

CountdownEvent – třída

Třída System.Threading.CountdownEvent představuje událost, která se nastaví, když jeho počet je nula. I když CountdownEvent.CurrentCount je větší než nula, vlákno, které volá CountdownEvent.Wait , je blokováno. Volání CountdownEvent.Signal pro snížení počtu událostí

Na rozdíl od ManualResetEvent nebo ManualResetEventSlim, které můžete použít k odblokování více vláken s signálem z jednoho vlákna, můžete použít CountdownEvent k odblokování jednoho nebo více vláken se signály z více vláken.

Další informace najdete v článku CountdownEvent a referenční informace k CountdownEvent rozhraní API.

Barrier – třída

Třída System.Threading.Barrier představuje bariéru spuštění vlákna. Vlákno, které volá metodu Barrier.SignalAndWait signály, že dosáhl bariéry a čeká, až ostatní účastníci vlákna dorazí do bariéry. Když se všechna vlákna účastníků dostanou do bariéry, budou pokračovat a bariéra se resetuje a lze ji znovu použít.

Před pokračováním do další fáze výpočtu můžete použít Barrier , když jedno nebo více vláken vyžaduje výsledky jiných vláken.

Další informace najdete v článku o bariérách a v referenčních informacích k Barrier rozhraní API.

Interlocked – třída

Třída System.Threading.Interlocked poskytuje statické metody, které provádějí jednoduché atomické operace s proměnnou. Mezi tyto atomické operace patří sčítání, zvýšení a dekrementace, výměna a podmíněná výměna, které závisí na porovnání, a operace čtení 64bitové celočíselné hodnoty.

Další informace najdete v referenčních informacích k Interlocked rozhraní API.

SpinWait – struktura

Struktura System.Threading.SpinWait poskytuje podporu pro čekání na základě číselníku. Můžete ji použít, když vlákno musí počkat na to, aby byla událost signalizovaná nebo byla splněna podmínka, ale pokud se očekává, že skutečná doba čekání bude menší než doba čekání požadovaná pomocí obslužného rutiny čekání nebo jinak blokující vlákno. Pomocí SpinWait, můžete zadat krátkou dobu, která se má otáčet při čekání, a pak výnos (například čekáním nebo spaním) pouze v případě, že podmínka nebyla splněna v zadaném čase.

Další informace najdete v článku o SpinWait a referenčních informacích k SpinWait rozhraní API.

Viz také