Lock Klasa

Definicja

Zapewnia mechanizm osiągnięcia wzajemnego wykluczenia w regionach kodu między różnymi wątkami.

public ref class Lock sealed
public sealed class Lock
type Lock = class
Public NotInheritable Class Lock
Dziedziczenie
Lock

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 nazywanymi sekcjami krytycznymi, aby zapobiec współbieżnym dostępom do zasobu. Lock Można 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 przytrzymaj lub jest właścicielem blokady, dopóki nie opuści blokady. Co najwyżej jeden wątek może przechowywać blokadę w danym momencie. Wątek może zawierać wiele blokad. Wątek może wprowadzać blokadę wiele razy 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 zakończona w metodzie języka C# async , upewnij się, że między wejściem a wyjściem nie await ma miejsca. Blokady są przechowywane przez wątki, a poniższy await kod 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, takie jak słowo kluczowe C# lub używa słowa kluczowego C# usinglock , ponieważ zapewniają one zamknięcie blokady w wyjątkowych przypadkach. Te wzorce mogą również mieć korzyści z wydajności związane z używaniem i Enter/TryEnterExit. 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 to coś innego, na przykład lub typ ogólny, taki jak ObjectT, można użyć innej implementacji, która nie jest wymienna (na przykład Monitor). Aby uzyskać więcej informacji, zobacz odpowiednie specyfikacje kompilatora.

Interrupt może przerywać wątki oczekujące na wprowadzenie blokady. Na Windows wątkach STA czeka na blokady zezwalają 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 / Notatka

Wątek, który wchodzi w blokadę, w tym wiele razy, takich jak rekursywnie, musi zamknąć blokadę taką samą liczbę razy, aby w pełni zamknąć blokadę i zezwolić innym wątkom na wejście do blokady. Jeśli wątek kończy się podczas przechowywania Lockelementu , zachowanie obiektu Lock staje się niezdefiniowane.

Caution

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ą wprowadzić 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 zakleszczeń. Rozważmy na przykład, że w jednym wątku T1 ścieżki kodu następuje blokada L1 , a następnie blokada L2 przed zakończeniem obu tych operacji, a w innym wątku T2 ścieżki kodu wprowadza oba blokady w odwrotnej kolejności. W tym scenariuszu może wystąpić następująca kolejność zdarzeń: T1 wprowadza L1L2wartość , T2T1 próbuje wprowadzić L2 i czekać, T2 próbuje wprowadzić L1 i czekać. Istnieje zakleszczenie między T1 i T2 , które nie można rozwiązać, a wszystkie inne wątki, które próbują wprowadzić jedną blokadę w przyszłości również powiesić.

Konstruktory

Nazwa Opis
Lock()

Inicjuje nowe wystąpienie klasy Lock.

Właściwości

Nazwa Opis
IsHeldByCurrentThread

Pobiera wartość wskazującą, czy blokada jest przechowywana przez bieżący wątek.

Metody

Nazwa Opis
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 określony obiekt jest równy bieżącemu obiektowi.

(Odziedziczone po Object)
Exit()

Zamyka blokadę.

GetHashCode()

Służy jako domyślna funkcja skrótu.

(Odziedziczone po Object)
GetType()

Pobiera Type bieżącego wystąpienia.

(Odziedziczone po Object)
MemberwiseClone()

Tworzy płytkią kopię bieżącego Object.

(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.

Dotyczy