Lock Класс

Определение

Предоставляет механизм достижения взаимного исключения в регионах кода между разными потоками.

public ref class Lock sealed
public sealed class Lock
type Lock = class
Public NotInheritable Class Lock
Наследование
Lock

Комментарии

Класс Lock можно использовать для определения регионов кода, требующих взаимоисключающего доступа между потоками процесса, часто называемыми критически важными разделами, чтобы предотвратить одновременный доступ к ресурсу. Lock Можно ввести и выйти, где область кода между вводом и выходом является критически важным разделом, связанным с блокировкой. Поток, который входит в блокировку, как сообщается, удерживает или владеет блокировкой, пока не завершится блокировка. По крайней мере один поток может хранить блокировку в любое время. Поток может содержать несколько блокировок. Поток может ввести блокировку несколько раз перед выходом из нее, например рекурсивно. Поток, который не может сразу ввести блокировку, может ждать, пока блокировка не будет введена или не истекает указанное время ожидания.

При использовании Enter методов для TryEnter ввода блокировки:

  • Убедитесь, что поток завершает блокировку Exit даже в случае исключений, например в C# с помощью try/finally блока.
  • При вводе и выходе блокировки в методе C# async убедитесь, что между вводом и выходом отсутствует await . Блокировки хранятся потоками и кодом, приведенным ниже await , может выполняться в другом потоке.

Рекомендуется использовать EnterScope метод с конструкцией языка, которая автоматически удаляет возвращаемое Lock.Scope значение, например ключевое слово C#, или использовать ключевое слово C# usinglock , так как это гарантирует, что блокировка завершается в исключительных случаях. Эти шаблоны также могут иметь преимущества производительности по сравнению с использованием Enter/TryEnter и Exit. Следующий фрагмент кода иллюстрирует различные шаблоны ввода и выхода из блокировки.

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(); }
        }
    }
}

При использовании ключевого слова C# lock или аналогично входу и выходу из блокировки тип выражения должен быть точно System.Threading.Lock. Если тип выражения является чем-либо другим, например Object универсальным типом, например Tуниверсальным типом, другой реализацией, которая не является взаимозаменяемой, можно использовать вместо этого (например Monitor, ). Дополнительные сведения см. в соответствующем спецификации компилятора.

Interrupt может прерывать потоки, ожидающие ввода блокировки. В потоках STA Windows ожидание блокировки разрешает перекачки сообщений, которые могут запускать другой код в том же потоке во время ожидания. Некоторые функции ожиданий можно переопределить пользовательским SynchronizationContext.

Note

Поток, который входит в блокировку, включая несколько раз, например рекурсивно, должен выйти из блокировки одинаковое количество раз, чтобы полностью выйти из блокировки и разрешить другим потокам войти в блокировку. Если поток завершается при удержании Lock, поведение не Lock определено.

Предостережение

Если в пути к коду поток может ввести несколько блокировок перед выходом из них, убедитесь, что все пути кода, которые могут ввести две из этих блокировок в одном потоке, введите их в одном порядке. В противном случае это может привести к взаимоблокировкам. Например, рассмотрим, что в одном потоке T1 пути кода блокируется блокировка L1L2 перед выходом из обоих, а другой поток T2 пути кода вводит обе блокировки в обратном порядке. В этом сценарии можно было бы выполнить следующий порядок событий: T1 ввод, ввод T1L2L1, T2 попытки ввода L2 и ожидания, T2 попытки ввода L1 и ожидания. Существует взаимоблокировка между T1 и T2 которые не могут быть разрешены, и любые другие потоки, которые пытаются ввести любую блокировку в будущем, также зависнет.

Конструкторы

Имя Описание
Lock()

Инициализирует новый экземпляр класса Lock.

Свойства

Имя Описание
IsHeldByCurrentThread

Возвращает значение, указывающее, удерживается ли блокировка текущим потоком.

Методы

Имя Описание
Enter()

Вводит блокировку, ожидая при необходимости, пока блокировка не будет введена.

EnterScope()

Вводит блокировку, ожидая при необходимости, пока блокировка не будет введена.

Equals(Object)

Определяет, равен ли указанный объект текущему объекту.

(Унаследовано от Object)
Exit()

Завершает блокировку.

GetHashCode()

Служит хэш-функцией по умолчанию.

(Унаследовано от Object)
GetType()

Возвращает Type текущего экземпляра.

(Унаследовано от Object)
MemberwiseClone()

Создает неглубокую копию текущей Object.

(Унаследовано от Object)
ToString()

Возвращает строку, представляющую текущий объект.

(Унаследовано от Object)
TryEnter()

Пытается ввести блокировку без ожидания.

TryEnter(Int32)

Пытается ввести блокировку, ожидая, если это необходимо для указанного числа миллисекунда, пока блокировка не будет введена.

TryEnter(TimeSpan)

Пытается ввести блокировку, ожидая, если это необходимо, пока блокировка не будет введена или не истекает указанное время ожидания.

Применяется к