Synchronizowanie danych wielowątkowych
Jeśli wiele wątków może wykonywać wywołania właściwości i metody pojedynczego obiektu, ważne jest, aby te wywołania były synchronizowane. W przeciwnym razie jeden wątek może przerwać działanie innego wątku, a obiekt może pozostać w nieprawidłowym stanie. Klasa, której składowe są chronione przed takimi przerwami, jest nazywana bezpieczną wątkowo.
Platforma .NET udostępnia kilka strategii synchronizowania dostępu do wystąpień i statycznych elementów członkowskich:
Zsynchronizowane regiony kodu. Możesz użyć Monitor obsługi klasy lub kompilatora dla tej klasy, aby zsynchronizować tylko blok kodu, który go potrzebuje, zwiększając wydajność.
Synchronizacja ręczna. Można użyć obiektów synchronizacji udostępnianych przez bibliotekę klas platformy .NET. Zobacz Omówienie elementów pierwotnych synchronizacji, w tym omówienie Monitor klasy.
Zsynchronizowane konteksty. Tylko w przypadku aplikacji .NET Framework i Xamarin można użyć polecenia SynchronizationAttribute , aby włączyć prostą, automatyczną synchronizację obiektów ContextBoundObject .
Klasy kolekcji w System.Collections.Concurrent przestrzeni nazw. Te klasy zapewniają wbudowane operacje dodawania i usuwania. Aby uzyskać więcej informacji, zobacz Kolekcje wątków Sejf.
Środowisko uruchomieniowe języka wspólnego udostępnia model wątków, w którym klasy dzielą się na wiele kategorii, które można synchronizować na różne sposoby w zależności od wymagań. W poniższej tabeli przedstawiono obsługę synchronizacji dla pól i metod z daną kategorią synchronizacji.
Kategoria | Pola globalne | Pola statyczne | Metody statyczne | Pola wystąpienia | Metody wystąpienia | Określone bloki kodu |
---|---|---|---|---|---|---|
Brak synchronizacji | Nie | Nie. | Nie. | Nie. | Nie. | Nie. |
Kontekst zsynchronizowany | Nie | Nie. | Nie. | Tak | Tak | Nie. |
Zsynchronizowane regiony kodu | Nie | Nie. | Tylko w przypadku oznaczenia | Nie. | Tylko w przypadku oznaczenia | Tylko w przypadku oznaczenia |
Synchronizacja ręczna | Ręcznie | Ręcznie | Ręcznie | Ręcznie | Ręcznie | Ręcznie |
Brak synchronizacji
Jest to wartość domyślna dla obiektów. Dowolny wątek może uzyskiwać dostęp do dowolnej metody lub pola w dowolnym momencie. Tylko jeden wątek jednocześnie powinien uzyskiwać dostęp do tych obiektów.
Synchronizacja ręczna
Biblioteka klas platformy .NET udostępnia wiele klas do synchronizowania wątków. Zobacz Omówienie elementów pierwotnych synchronizacji.
Zsynchronizowane regiony kodu
Klasy lub słowa kluczowego kompilatora można używać Monitor do synchronizowania bloków kodu, metod wystąpienia i metod statycznych. Brak obsługi synchronizowanych pól statycznych.
Zarówno Visual Basic, jak i C# obsługują oznaczanie bloków kodu za pomocą określonego słowa kluczowego języka, lock
instrukcji w języku C# lub instrukcji SyncLock
w Visual Basic. Gdy kod jest wykonywany przez wątek, podejmowana jest próba uzyskania blokady. Jeśli blokada została już nabyta przez inny wątek, bloki wątku do momentu udostępnienia blokady. Gdy wątek kończy zsynchronizowany blok kodu, blokada zostanie zwolniona, niezależnie od tego, jak wątek zamyka blok.
Uwaga
Począwszy od języka C# 13, instrukcja rozpoznaje, lock
czy zablokowany obiekt jest wystąpieniem System.Threading.Lock i używa EnterScope
metody do utworzenia zsynchronizowanego regionu. , lock
gdy element docelowy nie jest wystąpieniem Lock
, a SyncLock
instrukcje są implementowane przy użyciu metod Monitor.Enter i Monitor.Exit, więc inne metody Monitor mogą być używane w połączeniu z nimi w zsynchronizowanym regionie.
Możesz również ozdobić metodę MethodImplAttribute wartością z wartością MethodImplOptions.Synchronized, która ma taki sam efekt jak użycie Monitor lub jedno ze słów kluczowych kompilatora w celu zablokowania całej treści metody.
Thread.Interrupt Może służyć do przerwania wątku poza operacje blokujące, takie jak oczekiwanie na dostęp do zsynchronizowanego regionu kodu. Thread.Interrupt służy również do przerywania wątków poza operacjami, takimi jak Thread.Sleep.
Ważne
Nie blokuj typu — czyli typeof(MyType)
w języku C#, GetType(MyType)
Visual Basic lub MyType::typeid
C++ — w celu ochrony static
metod (Shared
metod w Visual Basic). Zamiast tego użyj prywatnego obiektu statycznego. Podobnie nie używaj this
w języku C# (Me
w Visual Basic) do blokowania metod wystąpień. Zamiast tego użyj obiektu prywatnego. Klasę lub wystąpienie można zablokować za pomocą kodu innego niż własny, co może spowodować zakleszczenia lub problemy z wydajnością.
Obsługa kompilatora
Zarówno Visual Basic, jak i C# obsługują słowo kluczowe języka, które używa Monitor.Enter i Monitor.Exit do blokowania obiektu. Język Visual Basic obsługuje instrukcję SyncLock ; Język C# obsługuje instrukcję lock .
W obu przypadkach, jeśli w bloku kodu zostanie zgłoszony wyjątek, blokada uzyskana przez blokadę lub funkcja SyncLock zostanie zwolniona automatycznie. Kompilatory języka C# i Visual Basic emitują blok try/finally z ciągiem Monitor.Enter na początku próby i Monitor.Exit w bloku na końcu. Jeśli wyjątek zostanie zgłoszony wewnątrz blokady lub bloku SyncLock, program obsługi na koniec zostanie uruchomiony, aby umożliwić wykonywanie dowolnej pracy czyszczenia.
Kontekst zsynchronizowany
Tylko w aplikacjach platformy .NET Framework i Xamarin można używać SynchronizationAttribute elementu on on dowolny ContextBoundObject do synchronizowania wszystkich metod i pól wystąpień. Wszystkie obiekty w tej samej domenie kontekstu mają tę samą blokadę. Wiele wątków może uzyskiwać dostęp do metod i pól, ale tylko jeden wątek jest dozwolony w dowolnym momencie.