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íž členové jsou chráněni před takovým přerušením, se nazývá vlákno-bezpečné.
.NET poskytuje několik strategií pro synchronizaci 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 pro aplikace .NET Framework a Xamarin můžete povolit SynchronizationAttribute jednoduchou automatickou synchronizaci ContextBoundObject objektů.
Třídy kolekce v System.Collections.Concurrent oboru názvů. Tyto třídy poskytují integrované synchronizované operace přidání a odebrání. Další informace naleznete v tématu Kolekce thread-Sejf.
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.
Kategorie | Globální pole | Statická pole | Statické metody | Pole instance | Metody instancí | Konkrétní bloky kódu |
---|---|---|---|---|---|---|
Žádná synchronizace | No | No | No | No | No | Ne |
Synchronizovaný kontext | No | No | No | Ano | Ano | No |
Synchronizované oblasti kódu | No | Ne | Pouze pokud je označeno | No | Pouze pokud je označeno | Pouze pokud je označeno |
Ruční synchronizace | Ruční | Ruční | Ruční | Ruční | Ruční | Ruční |
Žá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. Pro synchronizovaná statická pole není podporována.
Jazyk Visual Basic i C# podporují označení bloků kódu určitým klíčovým slovem jazyka, lock
příkazem v jazyce C# nebo příkazem SyncLock
v jazyce 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ískal jiný vlákno, vlákno blokuje, dokud zámek nebude k dispozici. Když vlákno ukončí synchronizovaný blok kódu, zámek se uvolní bez ohledu na to, jak vlákno ukončí blok.
Poznámka:
Počínaje jazykem C# 13 příkaz rozpozná, lock
jestli je uzamčený objekt instancí System.Threading.Lock a používá metodu EnterScope
k vytvoření synchronizované oblasti. , lock
pokud cíl není Lock
instance a SyncLock
příkazy jsou implementovány pomocí Monitor.Enter , a Monitor.Exit, takže ostatní metody Monitor lze použít ve spojení s nimi v rámci 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.
Důležité
Nezamkněte typ – to znamená v typeof(MyType)
jazyce C#, GetType(MyType)
v jazyce Visual Basic nebo MyType::typeid
v jazyce C++ – za účelem ochrany static
metod (Shared
metod v jazyce Visual Basic). Místo toho použijte privátní statický objekt. Podobně nepoužívejte this
v jazyce C# (Me
v jazyce 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í klíčové slovo jazyka, které používá Monitor.Enter a Monitor.Exit zamkne objekt. Visual Basic podporuje příkaz SyncLock ; Jazyk C# podporuje příkaz lock .
V obou případech, pokud je v bloku kódu vyvolán výjimka, zámek získaný zámkem nebo SyncLock se uvolní automaticky. Kompilátory jazyka C# a Visual Basic vygenerují blok try/finally s nástrojem Monitor.Enter na začátku tohoto pokusu a v bloku finally se vygeneruje příkaz Monitor.Exit. Pokud dojde k výjimce uvnitř zámku nebo bloku SyncLock, spustí se obslužná rutina finally, která vám umožní provést jakoukoli vyčistit práci.
Synchronizovaný kontext
V aplikacích .NET Framework a Xamarin můžete k synchronizaci všech metod a polí použít SynchronizationAttribute libovolnou ContextBoundObject instanci. 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.