Synchronizace dat pro multithreading

Pokud více vláken může volat vlastnosti a metody jednoho objektu, je důležité, aby tato volání byla synchronizována. Jinak může jedno vlákno přerušit to, co dělá jiné vlákno, a objekt by mohl zůstat v neplatném stavu. Třída, jejíž členy jsou chráněny před takovými přerušeními, se nazývá bezpečná z hlediska vláken.

.NET poskytuje několik strategií synchronizace přístupu k instancím a statickým členům:

  • Synchronizované oblasti kódu Pomocí podpory třídy nebo kompilátoru Monitor pro tuto třídu můžete synchronizovat pouze blok kódu, který ho potřebuje, a zvýšit výkon.

  • Ruční synchronizace Synchronizační objekty poskytované knihovnou tříd .NET můžete použít. Viz Přehled primitiv synchronizace, která obsahuje diskuzi o Monitor třídě.

  • Synchronizované kontexty Pouze v aplikacích .NET Framework můžete použít SynchronizationAttribute k povolení jednoduché automatické synchronizace objektů ContextBoundObject.

  • Třídy kolekcí v oboru názvů System.Collections.Concurrent. Tyto třídy poskytují integrované synchronizované operace přidání a odebrání. Další informace viz Thread-Safe Kolekce.

Modul CLR (Common Language Runtime) poskytuje model vlákna, ve kterém třídy spadají do řady kategorií, které je možné synchronizovat různými způsoby v závislosti na požadavcích. Následující tabulka ukazuje, jaká podpora synchronizace je k dispozici pro pole a metody s danou kategorií synchronizace.

Category Globální pole Statická pole Statické metody Instanční pole Metody instancí Konkrétní bloky kódu
Žádná synchronizace Ne Ne Ne Ne Ne Ne
Synchronizovaný kontext Ne Ne Ne Yes Yes Ne
Synchronizované oblasti kódu Ne Ne Pouze pokud je označeno Ne Pouze pokud je označeno Pouze pokud je označeno
Ruční synchronizace Příručka Příručka Příručka Příručka Příručka Příručka

Žádná synchronizace

Toto je výchozí hodnota pro objekty. Jakékoli vlákno může kdykoli přistupovat k libovolné metodě nebo poli. K těmto objektům by mělo přistupovat pouze jedno vlákno najednou.

Ruční synchronizace

Knihovna tříd .NET poskytuje řadu tříd pro synchronizaci vláken. Viz přehled primitiv synchronizace.

Synchronizované oblasti kódu

Třídu nebo klíčové slovo kompilátoru Monitor můžete použít k synchronizaci bloků kódu, metod instance a statických metod. Synchronizovaná statická pole nejsou podporována.

Visual Basic i jazyk C# podporují označení bloků kódu určitým klíčovým slovem jazyka, lock příkaz v jazyce C# nebo SyncLock příkaz v Visual Basic. Při spuštění kódu vláknem se provede pokus o získání zámku. Pokud zámek již získalo jiné vlákno, vlákno se zablokuje, dokud se zámek neuvolní. Když vlákno ukončí synchronizovaný blok kódu, zámek se uvolní bez ohledu na to, jak vlákno ukončí blok.

Poznámka:

V .NET 9 a C# 13 nebo novějších, pokud je cíl vyhrazenou instancí System.Threading.Lock, příkaz lock používá Lock.EnterScope() k vytvoření synchronizované oblasti.

Visual Basic nepodporuje System.Threading.Lock v SyncLock, takže nadále používejte SyncLock s vyhrazeným soukromým referenčním typem.

Pokud cíl lock není instancí Lock a ve všech použitích SyncLock kompilátor používá Monitor.Enter a Monitor.Exit. Vzhledem k této implementaci můžete i nadále používat jiné Monitor metody v synchronizované oblasti.

Můžete také ozdobit metodu MethodImplAttribute s hodnotou MethodImplOptions.Synchronized, která má stejný účinek jako použití Monitor nebo jedno z klíčových slov kompilátoru k uzamčení celého těla metody.

Thread.Interrupt lze použít k přerušení vlákna z blokujících operací, jako je například čekání na přístup k synchronizované oblasti kódu. Thread.Interrupt se také používá k přerušení vláken mimo operace, jako je Thread.Sleep.

Important

Nezamkněte typ – to znamená v typeof(MyType) jazyce C#, GetType(MyType) v Visual Basic nebo MyType::typeid v jazyce C++ – za účelem ochrany static metod (Shared metod v Visual Basic). Místo toho použijte privátní statický objekt. Podobně nepoužívejte this v jazyce C# (Mev Visual Basic) k uzamčení metod instance. Místo toho použijte soukromý objekt. Třídu nebo instanci lze uzamknout jiným kódem, než je vaše vlastní, což může způsobit zablokování nebo problémy s výkonem.

Podpora kompilátoru

Visual Basic i C# podporují jazykový klíčový výraz, který používá Monitor.Enter a Monitor.Exit k uzamčení objektu. Visual Basic podporuje příkaz SyncLock; Jazyk C# podporuje příkaz lock.

V obou případech, pokud je v bloku kódu vyvolána výjimka, zámek získaný pomocí lock nebo SyncLock se automaticky uvolní. Kompilátory jazyka C# a Visual Basic vygenerují blok try/finally pomocí nástroje Monitor.Enter na začátku pokusu a monitor.Exit v bloku finally. Pokud je uvnitř bloku lock nebo SyncLock vyvolána výjimka, spustí se obslužný blok finally, aby vám umožnil provést veškeré potřebné vyčištění.

Synchronizovaný kontext

Pouze v aplikacích .NET Framework můžete použít SynchronizationAttribute u libovolné instance ContextBoundObject k synchronizaci všech instančních metod a polí. Všechny objekty ve stejné kontextové doméně sdílejí stejný zámek. Přístup k metodám a polím má více vláken, ale současně je povoleno pouze jedno vlákno.

Viz také