Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
My_shpory_Ivan_Ivanich (2).docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
149.35 Кб
Скачать

13. Класс монитора, конструкция lock()

Оператор lock

При помощи ключевого слова lock блок операторов можно пометить как важный фрагмент, получив блокировку взаимного исключения для указанного объекта, выполнив оператор, а затем сняв блокировку. Следующий пример включает оператор lock.

class Account

{

decimal balance;

private Object thisLock = new Object();

public void Withdraw(decimal amount)

{

lock (thisLock)

{

if (amount > balance)

throw new Exception("Insufficient funds");

balance -= amount;

}

}

}

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

Ключевое слово lock вызывает Enter в начале блока и Exit в конце блока.

Для блокировки рекомендуется определять объект private или переменную объекта private static, чтобы защитить данные, являющиеся общими для всех экземпляров.

Нельзя использовать ключевое слово await (подождите) в теле оператора lock.

Класс Monitor и блокировка

Ключевое слово lock на самом деле служит в C# быстрым способом доступа к средствам синхронизации, определенным в классе Monitor, который находится в пространстве имен System.Threading. В этом классе определен, в частности, ряд методов для управления синхронизацией. Например, для получения блокировки объекта вызывается метод Enter (), а для снятия блокировки — метод Exit (). Ниже приведены общие формы этих методов:

public static void Enter(object obj) public static void Exit (object obj)

где obj обозначает синхронизируемый объект. Если же объект недоступен, то после вызова метода Enter () вызывающий поток ожидает до тех пор, пока объект не станет доступным. Тем не менее методы Enter () и Exit () применяются редко, поскольку оператор lock автоматически предоставляет эквивалентные средства синхронизации потоков. Именно поэтому оператор lock оказывается “более предпочтительным" для получения блокировки объекта при программировании на С#. Впрочем, один метод из класса Monitor может все же оказаться полезным. Это метод TryEnter (), одна из общих форм которого приведена ниже.

public static bool TryEnter(object obj)

Этот метод возвращает логическое значение true, если вызывающий поток получает блокировку для объекта obj, а иначе он возвращает логическое значение false. Но в любом случае вызывающему потоку придется ждать своей очереди. С помощью метода TryEnter () можно реализовать альтернативный вариант синхронизации потоков, если требуемый объект временно недоступен.

14. Атомарная синхронизация и класс Interlocked

Класс Interlocked позволяет создавать простые операторы для атомарных операций с переменными. Например, операция i++ не является безопасной в отношении потоков. Она подразумевает извлечение значения из памяти, увеличение этого значения на 1 и его обратное сохранение в памяти. Такие операции могут прерываться планировщиком потоков. Класс Interlocked предоставляет методы, позволяющие выполнять инкремент, декремент, обмен и считывание значений в безопасной к потокам манере.

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

Член

Назначение

CompareExchange()

Безопасно проверяет два значения на эквивалентность. Если они эквивалентны, изменяет одно из значений на третье

Decrement()

Безопасно уменьшает значение на 1

Exchange()

Безопасно меняет два значения местами

Increment()

Безопасно увеличивает значение на 1

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

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

Методы Increment и Decrement увеличивают или уменьшают значение переменной и сохраняют результат в одной операции. На большинстве компьютеров увеличение значения переменной не является атомарной операцией, а требует следующих шагов:

  1. Загрузить значение из переменной экземпляра в регистр.

  2. Увеличить или уменьшить значение.

  3. Сохранить значение в переменной экземпляра.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]