2.42M
Категория: ПрограммированиеПрограммирование

«Системное программирование» тема: «Асинхронные вычисления. Семафор, монитор» (Лекция 17)

1.

Лекция №17
по курсу
«Системное программирование»
тема: «Асинхронные вычисления.
Семафор, монитор»
Лектор: д.т.н., Оцоков Шамиль Алиевич,
email: [email protected]
Москва, 2021

2.

2

3.

Асинхронность
3

4.

Асинхронность
4

5.

Асинхронность
5

6.

Асинхронность
6

7.

Асинхронность
Асинхронность позволяет вынести отдельные задачи из основного потока в специальные
асинхронные методы или блоки кода. Особенно это актуально в графических программах,
где продолжительные задачи могу блокировать интерфейс пользователя. И чтобы этого не
произошло, нужно задействовать асинхронность. Также асинхронность несет выгоды в вебприложениях при обработке запросов от пользователей, при обращении к базам данных или
сетевым ресурсам. При больших запросах к базе данных асинхронный метод просто уснет на
время, пока не получит данные от БД, а основной поток сможет продолжить свою работу. В
синхронном же приложении, если бы код получения данных находился в основном потоке,
этот поток просто бы блокировался на время получения данных.
Ключевыми для работы с асинхронными вызовами в C# являются два ключевых слова: async
и await, цель которых - упростить написание асинхронного кода. Они используются вместе
для создания асинхронного метода.
Асинхронный метод обладает следующими признаками:
В заголовке метода используется модификатор async
Метод содержит одно или несколько выражений await
В качестве возвращаемого типа используется один из следующих:
void, Task, Task<T>, ValueTask<T>
7

8.

Асинхронность
Асинхронный метод, как и обычный, может использовать любое количество параметров или
не использовать их вообще.
Также стоит отметить, что слово async, которое указывается в определении метода, не делает
автоматически метод асинхронным. Оно лишь указывает, что данный метод может
содержать одно или несколько выражений await.
Выражение await определяет задачу, которая будет выполняться асинхронно. В данном
случае подобная задача представляет выполнение функции факториала:
await Task.Run(()=>Factorial());
StreamWriter writer = new StreamWriter("hello.txt", false);
await writer.WriteLineAsync("Hello"); // асинхронная запись в файл
8

9.

Асинхронность
static void Factorial()
{
int result = 1;
for (int i = 1; i <= 6; i++)
{
result *= i;
}
Thread.Sleep(8000);
Console.WriteLine($"Факториал равен {result}");
}
// определение асинхронного метода
static async void FactorialAsync()
{
await Task.Run(()=>Factorial()); // вызов асинхронной операции
}
// второй вариант через лямбда выражение
static async void FactorialAsync()
{
await Task.Run(() =>
{
int result = 1;
for (int i = 1; i <= 6; i++)
{
result *= i;
}
Thread.Sleep(8000);
Console.WriteLine($"Факториал равен {result}");
});
}
Литература
https://metanit.com/sharp/tutorial/13.3.php
https://alekseev74.ru/lessons/show/aspnetcore-mvc/async-await
9

10.

Синхронизация переменных
В многопоточной среде к одной и той же переменной могут обращаться два или
более потоков. Если операция
выполняется над общей переменной, является атомарным или потокобезопасной.
В атомарной операции только один поток за раз может выполнять один оператор.
В то время как в неатомарной операции более одного потока получают доступ и
манипулируют значением общей переменной, которая дает неточный результат
(например, если один поток читает значение, а другой поток в то же время
редактирует его).
10

11.

Синхронизация переменных
Два потока обращаются к одновременно манипулируя значением «num»
1. Lock
2. Monitor
3. Interlock
lock(object)
Блокировка - это ключевое слово C # предотвращает выполнение одним потоком
того же блока кода, что и другой поток.
Такой блок кода называется заблокированным кодом.
Следовательно, если поток пытается выполнить заблокированный код, он
будет ждать, пока объект не будет выпущен.
Ключевое слово блокировки вызывает Enter в начале блока и Exit в конце.
блока.
Лучше всего использовать ключевое слово lock с частным объектом или с
переменной частного статического объекта, чтобы защитить данные, общие для
всех экземпляров.
11

12.

Синхронизация переменных
Два потока обращаются к одновременно манипулируя значением «num»
1. Lock
2. Monitor
3. Interlock
Оператор lock получает взаимоисключающую блокировку заданного объекта
перед выполнением определенных операторов, а затем снимает блокировку. Во
время блокировки поток, удерживающий блокировку, может снова поставить и
снять блокировку. Любой другой поток не может получить блокировку и ожидает
ее снятия.
Оператор lock имеет форму
lock (x)
{
// Your code...
}
12

13.

Синхронизация переменных
В следующем примере определяется класс Account, который синхронизирует доступ к
закрытому полю balance путем блокировки выделенного экземпляра balanceLock.
Использование того же экземпляра для блокировки гарантирует, что поле balance не смогут
одновременно обновить два потока, пытающиеся вызвать методы Debit или Credit
одновременно.
13

14.

Синхронизация переменных
Monitor
Класс монитора также гарантирует, что никакой другой поток не сможет выполнить тот же
участок кода или разделяемую память пока он не будет выполнен владельцем блокировки.
Метод Monitor.Enter или Monitor.TryEnter используется для блокировки блока кода для других
потоков и запретить другим потокам выполнять его.
Метод Monitor.Exit используется для разблокировки заблокированного кода для другого
потока и разрешения другие потоки для его выполнения.
Класс Interlocked используется для синхронизации доступа к объектам разделяемой памяти
между несколькими потоками.
Класс Interlocked обеспечивает следующую полезную операцию с общей памятью
14

15.

DeadLock
В многопоточной среде может возникнуть тупиковая блокировка; приложение зависает,
потому что два или более действия ждут завершения друг друга.
Обычно это происходит, когда общий ресурс заблокирован одним
поток, а другой поток ожидает доступа к нему.
1. Tsk1 получает блокировку thislockA.
2. Tsk2 получает блокировку thislockB.
3. Tsk1 пытается получить блокировку thislockB, но она уже удерживается Tsk2 и,
следовательно,
Tsk1 блокируется до тех пор, пока не будет освобожден thislockB.
4. Tsk2 пытается получить блокировку thislockA, но она удерживается Tsk1 и, следовательно,
Tsk2.
блокируется до тех пор, пока не будет отпущена «thislockA».
На этом этапе оба потока заблокированы и никогда не проснутся. Следовательно,
приложение зависло.
15

16.

Cancellation Token
CancellationToken распространяет уведомление об отмене на такие операции, как потоки,
рабочие элементы пула потоков или задача.
Отмена происходит при запросе кода, вызывающего метод CancellationTokenSource.Cancel, и
затем делегат пользователя завершает операцию. Однако операцию можно прервать:
1. просто вернувшись от делегата;
2. путем вызова метода CancellationTokenSource.Cancel.
Ниже приведены общие шаги для реализации модели отмены:
1. Создайте экземпляр CancellationTokenSource.
2. Получите CancellationToken из свойства CancellationTokenSource.Token.
3. Передайте CancellationToken каждой задаче или потоку, ожидающему отмены.
4. Обеспечьте механизм для каждой задачи или потока, чтобы реагировать на отмену.
5. Вызовите метод CancellationTokenSource.Cancel, чтобы уведомить о
отмена.
16
English     Русский Правила