Lock Klasa
Definicja
Ważne
Niektóre informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany przed wydaniem. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.
Uwaga
Aby korzystać z tego interfejsu API w wersji zapoznawczej, należy włączyć funkcje w wersji zapoznawczej w projekcie, ustawiając właściwość EnablePreviewFeatures
na True
w pliku projektu. Aby uzyskać więcej informacji, zobacz https://aka.ms/dotnet-preview-features.
Zapewnia mechanizm umożliwiający osiągnięcie wzajemnego wykluczenia w regionach kodu między różnymi wątkami.
public ref class Lock sealed
[System.Runtime.Versioning.RequiresPreviewFeatures]
public sealed class Lock
[<System.Runtime.Versioning.RequiresPreviewFeatures>]
type Lock = class
Public NotInheritable Class Lock
- Dziedziczenie
-
Lock
- Atrybuty
Uwagi
Klasa Lock może służyć do definiowania regionów kodu, które wymagają wzajemnie wykluczania dostępu między wątkami procesu, często nazywanych sekcjami krytycznymi, aby zapobiec współbieżnym dostępom do zasobu. Można Lock
wprowadzić i zakończyć działanie, gdzie region kodu między wejściem i wyjściem jest sekcją krytyczną skojarzona z blokadą. Wątek, który wchodzi w blokadę, mówi się, że trzyma lub jest właścicielem blokady, dopóki nie zamknie blokady. Co najwyżej jeden wątek może przechowywać blokadę w danym momencie. Wątek może przechowywać wiele blokad. Wątek może wielokrotnie wprowadzać blokadę przed jej zamknięciem, na przykład rekursywnie. Wątek, który nie może natychmiast wprowadzić blokady, może poczekać na wprowadzenie blokady lub do momentu wygaśnięcia określonego limitu czasu.
W przypadku używania Enter metod lub TryEnter do wprowadzania blokady:
- Upewnij się, że wątek zamyka blokadę Exit nawet w przypadku wyjątków, takich jak w języku C#, przy użyciu
try/finally
bloku. - Gdy blokada zostanie wprowadzona i zamknięta w metodzie języka C#
async
, upewnij się, że między wejściem a wyjściem nieawait
ma. Blokady są przechowywane przez wątki, a poniższy kodawait
może działać w innym wątku.
Zaleca się użycie EnterScope metody z konstrukcją języka, która automatycznie usuwa zwracane Lock.Scope słowo kluczowe C# lub używa słowa kluczowego C# using
lock
, ponieważ zapewnia to zamknięcie blokady w wyjątkowych przypadkach. Te wzorce mogą również mieć korzyści z wydajności związane z używaniem Enter/TryEnter
i Exit
. Poniższy fragment kodu ilustruje różne wzorce wprowadzania i zamykania blokady.
public sealed class ExampleDataStructure
{
private readonly Lock _lockObj = new();
public void Modify()
{
lock (_lockObj)
{
// Critical section associated with _lockObj
}
using (_lockObj.EnterScope())
{
// Critical section associated with _lockObj
}
_lockObj.Enter();
try
{
// Critical section associated with _lockObj
}
finally { _lockObj.Exit(); }
if (_lockObj.TryEnter())
{
try
{
// Critical section associated with _lockObj
}
finally { _lockObj.Exit(); }
}
}
}
W przypadku używania słowa kluczowego C# lock
lub podobnego do wprowadzania i zamykania blokady typ wyrażenia musi być dokładnie System.Threading.Lock
. Jeśli typ wyrażenia jest czymkolwiek innym, takim jak lub typ T
ogólny, taki jak Object
, można użyć innej implementacji, która nie jest wymienna (na przykład Monitor). Aby uzyskać więcej informacji, zobacz odpowiednią specyfikację kompilatora.
Interrupt może przerywać wątki oczekujące na wprowadzenie blokady. W wątkach STA systemu Windows czeka na blokady zezwalające na pompowanie komunikatów, które mogą uruchamiać inny kod w tym samym wątku podczas oczekiwania. Niektóre funkcje oczekiwania mogą zostać zastąpione przez niestandardowy SynchronizationContextelement .
Uwaga
Wątek, który wprowadza blokadę, w tym wiele razy, na przykład rekursywnie, musi zamknąć blokadę taką samą liczbę razy, aby w pełni zamknąć blokadę i zezwolić innym wątkom na wprowadzanie blokady. Jeśli wątek kończy się podczas przechowywania Lock
elementu , zachowanie Lock
obiektu staje się niezdefiniowane.
Przestroga
Jeśli na ścieżce kodu wątek może wprowadzić wiele blokad przed ich zamknięciem, upewnij się, że wszystkie ścieżki kodu, które mogą wprowadzać dowolne dwa z tych blokad w tym samym wątku, wprowadź je w tej samej kolejności. W przeciwnym razie może to prowadzić do zakleszczenia. Rozważmy na przykład, że w jednym wątku T1
T2
ścieżki kodu wprowadza blokadęL1
, a następnie blokada L2
przed zamknięciem obu wątków ścieżki kodu wprowadza obie blokady w odwrotnej kolejności. W tym scenariuszu może wystąpić następująca kolejność zdarzeń: T1
wprowadza , T2
T1
L2
L1
próbuje wprowadzić i czekać, T2
próbuje wprowadzić L2
L1
i czekać. Istnieje zakleszczenie między T1
i T2
nie można go rozwiązać, a wszystkie inne wątki, które próbują wprowadzić jedną blokadę w przyszłości, również się powiesi.
Konstruktory
Lock() |
Inicjuje nowe wystąpienie klasy Lock. |
Właściwości
IsHeldByCurrentThread |
Pobiera wartość wskazującą, czy blokada jest przechowywana przez bieżący wątek. |
Metody
Enter() |
Wprowadza blokadę, czekając w razie potrzeby do momentu wprowadzenia blokady. |
EnterScope() |
Wprowadza blokadę, czekając w razie potrzeby do momentu wprowadzenia blokady. |
Equals(Object) |
Określa, czy dany obiekt jest taki sam, jak bieżący obiekt. (Odziedziczone po Object) |
Exit() |
Zamyka blokadę. |
GetHashCode() |
Służy jako domyślna funkcja skrótu. (Odziedziczone po Object) |
GetType() |
Type Pobiera bieżące wystąpienie. (Odziedziczone po Object) |
MemberwiseClone() |
Tworzy płytkią kopię bieżącego Objectelementu . (Odziedziczone po Object) |
ToString() |
Zwraca ciąg reprezentujący bieżący obiekt. (Odziedziczone po Object) |
TryEnter() |
Próbuje wprowadzić blokadę bez oczekiwania. |
TryEnter(Int32) |
Próbuje wprowadzić blokadę, czekając w razie potrzeby dla określonej liczby milisekund do momentu wprowadzenia blokady. |
TryEnter(TimeSpan) |
Próbuje wprowadzić blokadę, czekając w razie potrzeby do momentu wprowadzenia blokady lub do momentu wygaśnięcia określonego limitu czasu. |