Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
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.
.NET udostępnia kilka strategii synchronizacji dostępu do składników instancyjnych i statycznych:
Zsynchronizowane regiony kodu. Możesz użyć klasy Monitor lub obsługi kompilatora dla tej klasy, aby zsynchronizować tylko blok kodu, który tego wymaga, zwiększając wydajność.
Synchronizacja ręczna. Można użyć obiektów synchronizacji udostępnianych przez bibliotekę klas .NET. Zobacz Omówienie elementów pierwotnych synchronizacji, w tym omówienie Monitor klasy.
Zsynchronizowane konteksty. Tylko w przypadku aplikacji platformy .NET Framework można użyć polecenia SynchronizationAttribute , aby włączyć prostą, automatyczną synchronizację obiektówContextBoundObject.
Klasy kolekcji w przestrzeni nazw System.Collections.Concurrent. Te klasy zapewniają wbudowane zsynchronizowane operacje dodawania i usuwania. Aby uzyskać więcej informacji, zobacz Thread-Safe Kolekcje.
Ś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.
| Category | 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 | Instrukcja | Instrukcja | Instrukcja | Instrukcja | Instrukcja | Instrukcja |
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 .NET udostępnia szereg klas do synchronizowania wątków. Zobacz Omówienie elementów pierwotnych synchronizacji.
Zsynchronizowane regiony kodu
Można użyć klasy Monitor lub słowa kluczowego kompilatora do synchronizowania bloków kodu, metod instancji 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 SyncLock instrukcji w Visual Basic. Gdy kod jest wykonywany przez wątek, podejmowana jest próba uzyskania blokady. Jeśli blokada została już uzyskana przez inny wątek, wątek zostaje zablokowany do momentu, aż blokada stanie się dostępna. Gdy wątek kończy zsynchronizowany blok kodu, blokada zostanie zwolniona, niezależnie od tego, jak wątek zamyka blok.
Note
W platformie .NET 9 i języku C# 13 lub nowszym, jeśli obiekt docelowy lock jest dedykowanym wystąpieniem System.Threading.Lock, instrukcja lock używa elementu Lock.EnterScope() w celu utworzenia zsynchronizowanego regionu.
Visual Basic nie obsługuje System.Threading.Lock w SyncLock, dlatego nadal używaj SyncLock z dedykowanym prywatnym typem referencyjnym.
Jeśli obiekt docelowy lock nie jest wystąpieniem Lock, to we wszystkich zastosowaniach SyncLock kompilator używa Monitor.Enter i Monitor.Exit. Z powodu tej implementacji nadal można używać innych Monitor metod w zsynchronizowanych regionach.
Możesz również opatrzyć metodę elementem MethodImplAttribute o wartości MethodImplOptions.Synchronized, co daje taki sam efekt jak użycie Monitor lub jednego ze słów kluczowych kompilatora w celu zablokowania całego ciała 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) w 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 należy używać 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. 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 nałożona za pomocą lock lub SyncLock zostanie zwolniona automatycznie. Kompilatory języków C# i Visual Basic generują blok try/finally z wywołaniem Monitor.Enter na początku bloku try oraz z wywołaniem Monitor.Exit w bloku finally. Jeśli wyjątek zostanie zgłoszony wewnątrz bloku lock lub SyncLock, zostanie uruchomiona obsługa finally, umożliwiając wykonanie wszelkich czynności porządkowych.
Kontekst zsynchronizowany
Tylko w aplikacjach .NET Framework można użyć SynchronizationAttribute dla dowolnego obiektu ContextBoundObject, aby zsynchronizować wszystkie metody i pola instancji. 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.