Udostępnij za pośrednictwem


Lock Klasa

Definicja

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 nie await ma. Blokady są przechowywane przez wątki, a poniższy kod await 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# usinglock , 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 Togó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 Lockelementu , 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 T1T2 ś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 , T2T1L2L1próbuje wprowadzić i czekać, T2 próbuje wprowadzić L2L1 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.

Dotyczy