Similar presentations:
Основы многопоточного программирования. Общая информация
1.
Основы многопоточногопрограммирования
1
2.
ПотокиОБЩАЯ ИНФОРМАЦИЯ
2
3.
Общая информацияПото́к выполне́ния (англ. thread — нить) —
наименьшая единица обработки, исполнение
которой может быть назначено ядром операционной
системы.
3
4.
Общая информацияПоток выполнения находится внутри процесса.
Несколько потоков выполнения могут существовать в
рамках одного и того же процесса и совместно
использовать ресурсы, такие как память, тогда как
процессы не разделяют этих ресурсов.
4
5.
Общая информацияПроцесс содержит как минимум один (первичный) поток.
5
6.
Общая информацияСоздание потоков требует от ОС меньших накладных
расходов, чем процессов.
В отличие от процессов, все потоки одного процесса
всегда принадлежат одному приложению, поэтому ОС
изолирует потоки в гораздо меньшей степени, нежели
процессы в традиционной мультипрограммной системе.
Все потоки одного процесса используют общие файлы,
таймеры, устройства, одно и то же адресное
пространство
6
7.
Общая информацияДиспетчеризация – это переключение процессора с одного
потока на другой.
Процесс диспетчеризации:
Сохранение контекста потока, который
сменить.
Загрузка контекста нового потока.
Запуск нового потока на выполнение.
требуется
7
8.
Общая информацияВ большинстве OS используется
алгоритм диспетчеризации.
вытесняющий
8
9.
Общая информацияВ основе многих вытесняющих алгоритмов планирования
лежит концепция квантования. В соответствии с этой
концепцией каждому потоку поочередно для выполнения
предоставляется ограниченный непрерывный период
процессорного времени — квант.
9
10.
Общая информацияСмена активного потока происходит, если:
- поток завершился;
- произошла ошибка;
- поток перешел в состояние ожидания;
- исчерпан квант процессорного времени, отведенный
данному потоку.
10
11.
Общая информацияПоток завершен или
произошла ошибка
Активное состояние
(Выполнение)
Поток обратился
к устройству
ввода/вывода
Поток получил квант
времени
Поток израсходовал
квант времени
Готовность
Ожидание
Ожидание завершено
11
12.
Общая информацияУ каждого потока есть свой приоритет
Операционная система планирует к исполнению более
приоритетные потоки или выделяет приоритетным потокам
больший квант времени.
12
13.
Общая информацияПотоки получают приоритеты на базе классов приоритета
своих процессов.
13
14.
Общая информацияПри создании потока его приоритет по умолчанию
устанавливается равным приоритету процесса.
Приоритеты потоков могут принимать значения в
интервале ±2 относительно базового приоритета процесса.
14
15.
Общая информацияПри создании потока его приоритет по умолчанию
устанавливается равным приоритету процесса.
Приоритеты потоков могут принимать значения в
интервале ±2 относительно базового приоритета процесса.
15
16.
Общая информацияУровни приоритета потоков (в порядке убывания):
Highest
Above normal
Normal
Below normal
Lowest
16
17.
ПотокиПРОСТРАНСТВО ИМЕН SYSTEM.THREADING
17
18.
Пространство имен System.ThreadingКлассы,
поддерживающие
программирование, определены
имен System.Threading.
многопоточное
в пространстве
18
19.
Пространство имен System.ThreadingInterlocked Этот тип обеспечивает элементарные операции
для переменных, которые совместно используются
несколькими потоками.
Monitor Этот тип обеспечивает синхронизацию потоковых
объектов, используя блокировки и ожидания / сигналы.
Ключевое слово C# lock использует скрытый объект Monitor.
Mutex Этот примитив синхронизации можно использовать
для синхронизации между границами домена приложения.
ParameterizedThreadStart Этот делегат позволяет потоку
вызывать методы, которые принимают любое количество
аргументов.
19
20.
Пространство имен System.ThreadingSemaphore Этот тип позволяет вам ограничить число потоков,
которые могут одновременно обращаться к ресурсу или
определенному типу ресурса.
Thread Этот тип представляет поток, который выполняется в
CLR. Используя этот тип, вы можете создавать
дополнительные потоки в исходном домене приложения.
ThreadPool Этот тип позволяет вам взаимодействовать с
поддерживаемым CLR пулом потоков в данном процессе.
ThreadPriority Это перечисление представляет уровень
приоритета потока (Самый высокий, Нормальный и т.д.).
20
21.
Пространство имен System.ThreadingThreadStart Этот делегат используется для указания метода,
вызываемого для данного потока. В отличие от делегата
ParameterizedThreadStart, цели ThreadStart всегда должны
иметь один и тот же прототип.
ThreadState Это перечисление определяет допустимые
состояния, которые может принимать поток (работает,
прерван и т.д.).
Timer Этот тип предоставляет механизм для выполнения
метода через определенные промежутки времени.
TimerCallback Этот тип делегата используется вместе с типами
Timer.
21
22.
ПотокиКЛАСС THREAD
22
23.
Класс ThreadКласс Thread представляет объектно-ориентированную
оболочку для заданного потока выполнения.
23
24.
Класс ThreadКласс Thread также определяет ряд методов (как
статических, так и на уровне экземпляров класса), которые
позволяют создавать новые потоки в приложении, а также
приостанавливать,
возобновлять,
останавливать
и
уничтожать определенный поток.
24
25.
Методы и свойства класса ThreadSleep() - Этот метод (статический) приостанавливает
текущий поток на указанное время. Когда поток
приостановлен, он не использует процессорное время.
IsAlive Возвращает логическое значение, которое
указывает, был ли этот поток запущен (и еще не
завершен или не прерван).
Name Позволяет установить понятное текстовое имя
темы.
25
26.
Методы и свойства класса ThreadPriority Получает или задает приоритет потока, которому
может быть присвоено значение из перечисления
ThreadPriority.
ThreadState Получает состояние этого потока, которому
может быть присвоено значение из перечисления
ThreadState.
Abort() Указывает CLR прекратить поток.
Join() Блокирует вызывающий поток до тех пор, пока не
закончится указанный поток (тот, в котором вызывается
Join ()).
26
27.
Методы и свойства класса ThreadResume() Возобновляет поток, который был ранее
приостановлен.
Start() Указывает CLR выполнить поток.
Suspend() Приостановляет поток. Если поток уже
приостановлен, вызов Suspend() не имеет никакого
эффекта.
27
28.
Класс Thread. Создание и запуск потокаКонструктор потока:
public Thread(ThreadStart точка_входа)
точка_входа — это имя метода, вызываемого с целью
начать выполнение потока
ThreadStart — делегат, определенный в среде .NET
Framework:
public delegate void ThreadStart ()
28
29.
Класс Thread. Создание и запуск потокаСозданный поток не начнет выполняться до тех пор,
пока не будет вызван его метод Start().
29
30.
Класс Thread. Создание и запуск потокаclass MyThread
{
public int Count;
string thrdName;
public MyThread(string name)
{
Count = 0;
thrdName = name;
}
30
31.
Класс Thread. Создание и запуск потока/// <summary>
/// Функция потока
/// </summary>
public void Run()
{
Console.WriteLine(thrdName + " начат.");
do
{
// Длительное вычисление
Thread.Sleep(500); // ждать 500 мс
Console.WriteLine($"В потоке {thrdName}, Count = {Count}");
Count++;
}
while (Count < 10);
Console.WriteLine(thrdName + " завершен.");
}
}
}
31
32.
Класс Thread. Создание и запуск потокаConsole.WriteLine("Основной поток начат.");
// Создать объект типа MyThread.
MyThread mt = new MyThread("Потомок #1");
// Создать поток из метода Run объекта MyThread.
Thread newThrd = new Thread(mt.Run);
// Начать выполнение потока.
newThrd.Start();
// параллельно выводить индикацию о выполнении
do
{
Console.Write(".");
Thread.Sleep(100);
}
while (mt.Count != 10);
Console.WriteLine("Основной поток завершен");
32
33.
Класс Thread. Создание и запуск потокаConsole.WriteLine("Основной поток начат.");
// Создать объект типа MyThread.
MyThread mt = new MyThread("Потомок #1");
// Создать поток из метода Run объекта MyThread.
Thread newThrd = new Thread(mt.Run);
// Начать выполнение потока.
newThrd.Start();
// параллельно выводить индикацию о выполнении
for (int i = 0; i < 20;i++)
{
Console.Write(".");
Thread.Sleep(100);
};
newThrd.Join();
Console.WriteLine("Основной поток завершен");
33
34.
Класс Thread. Создание и запуск потокаЗапуск потока при создании класса MyThread:
public MyThread(string name)
{
Count = 0;
Thrd = new Thread(this.Run);
Thrd.Name = name; // задать имя потока
Thrd.Start(); // начать поток
}
34
35.
Класс Thread. Создание и запуск потокаЕсли потоку нужно передать параметры, то они передается
потоку в следующей форме метода Start ():
public void Start(object arg)
35
36.
Класс Thread. Создание и запуск потокаpublic MyThread(string name, int max)
{
Count = 0;
Thrd = new Thread( new ParameterizedThreadStart(this.Run));
Thrd.Name = name; // задать имя потока
Thrd.Start(max); // начать поток
}
36
37.
Класс Thread. Создание и запуск потока/// <summary>
/// Функция потока
/// </summary>
void Run(object max)
{
var limit = (int)max;
Console.WriteLine(Thrd.Name + " начат.");
do
{
Thread.Sleep(500);
Console.WriteLine("В потоке " + Thrd.Name +
", Count = " + Count);
Count++;
}
while (Count < limit);
Console.WriteLine(Thrd.Name + " завершен.");
}
37
38.
Класс Thread. Пул потоковСоздание потоков требует времени. Если есть различные
короткие задачи, подлежащие выполнению, можно создать
набор потоков заранее и затем просто отправлять
соответствующие запросы
38
39.
Класс Thread. Пул потоковМногие приложения создают потоки, которые проводят
много
времени
в
спящем
состоянии,
ожидая
возникновения события. Другие потоки могут переходить в
спящее состояние только для того, чтобы периодически их
пробуждать для опроса об изменении или обновлении
информации о статусе. Пул потоков позволяет более
эффективно использовать потоки, предоставляя вашему
приложению пул рабочих потоков, которыми управляет
система.
39
40.
Класс Thread. Пул потоковДля управления пулом потоков используется класс
ThreadPool
40
41.
Класс Thread. Пул потоковЧтобы запросить обработку задачи потоком в пуле
потоков, вызовите метод QueueUserWorkItem.
Этот метод принимает в качестве параметра ссылку на
метод или делегат, который будет вызываться потоком,
выбранным из пула потоков.
41
42.
Класс Thread. Пул потоков// Постановка задачи в очередь
ThreadPool.QueueUserWorkItem(ThreadProc);
// Процедура потока
static void ThreadProc(Object stateInfo)
{
// код задачи
}
42
43.
Класс Thread. Пул потоковПул потоков управляет потоками эффективно, уменьшая
количество создаваемых, запускаемых и останавливаемых
потоков.
43
44.
Класс Thread. Пул потоков (ограничения)Все потоки в пуле потоков являются фоновыми. Сделать поток
из пула приоритетным не удастся.
Нельзя изменять приоритет или имя находящего в пуле
потока.
Потоки в пуле подходят для выполнения только коротких
задач. Если необходимо, чтобы поток функционировал все
время (как, например, поток средства проверки орфографии в
Word), его следует создавать с помощью класса Thread.
Созданный поток невозможно прерывать или находить по
имени.
44
45.
ПотокиСИНХРОНИЗАЦИЯ ПОТОКОВ
45
46.
Синхронизация потоковВо
многопоточных
приложениях
потоки
могут
использовать общие разделяемые ресурсы: процессорное
время, память, файлы, переменные.
46
47.
Синхронизация потоковНапример: все потоки в домене приложений имеют
одновременный доступ к общим данным приложения.
Может возникнуть состояние гонок, когда поток А будет
считывать данные, в то время как поток B будет изменять
эти данные
47
48.
Синхронизация потоковКакие данные прочитает поток А – до изменения или
после? И какие из этих значений считать правильными?
Дело в том, что мы точно не знаем, в какой
последовательности планировщик потоков будет выделять
кванты времени для каждого потока.
48
49.
Синхронизация потоковpublic class ConcurrentThread
{
Random r = new();
public void PrintNumbers()
{
for (int i = 0; i < 10; i++)
{
// Приостановить поток на случайное время
Thread.Sleep(100 * r.Next(5));
Console.Write($"{i}, ");
}
Console.WriteLine();
}
}
49
50.
Синхронизация потоковvar p = new ConcurrentThread();
// Создать 10 потоков
Thread[] threads = new Thread[10];
for (int i = 0; i < 10; i++)
{
threads[i] =
new Thread(p.PrintNumbers);
}
// Запустить все потоки
foreach (Thread t in threads)
t.Start();
Console.ReadLine();
50
51.
Синхронизация потоковПорядок выполнения
непредсказуем
созданных
потоков
абсолютно
51
52.
Синхронизация потоковДля синхронизации работы потоков используются разные
объекты – Monitor, Mutex, Semaphore и др.
52
53.
Синхронизация потоков (критическая секция)Ключевое слово lock позволяет определить область
операторов (критическую секцию), которые должны быть
синхронизированы между потоками.
lock(lockObj)
{синхронизируемые операторы }
53
54.
Синхронизация потоков (критическая секция)public class ConcurrentThread
{
object locker = new object();
Random r = new Random();
public void PrintNumbers()
{
lock(locker)
for (int i = 0; i < 10; i++)
{
// Приостановить поток на случайное время
Thread.Sleep(100 * r.Next(5));
Console.Write($"{i}, ");
}
Console.WriteLine();
}
}
54
55.
Синхронизация потоков (Monitor)Конструкция оператора lock инкапсулирует
синтаксис использования мониторов.
в
55
себе
56.
Синхронизация потоков (Monitor)Monitor.Enter(locker);
try
{
for (int i = 0; i < 10; i++)
{
// Приостановить поток на случайное время
}
Thread.Sleep(100 * r.Next(5));
Console.Write($"{i}, ");
}
finally
{
Monitor.Exit(locker);
}
56
57.
Синхронизация потоков (Mutex)Kласс
Mutex
является
классом-оберткой
соответствующим объектом ОС Windows «Mutex»
над
Особенностью
мьютекса
является
возможность
синхронизировать процессы. Для этого при создании
объекта нужно задать мьютексу имя.
57
58.
Синхронизация потоков (Mutex)Mutex mutex = new Mutex(false);
Random r = new Random();
public void PrintNumbers()
{
mutex.WaitOne();
}
for (int i = 0; i < 10; i++)
{
. . .
}
mutex.ReleaseMutex();
58
59.
Синхронизация потоков (Semaphore)Kласс Semaphore является классом-оберткой над
соответствующим объектом ОС Windows «Semaphore»
Semaphore работает аналогично классу Mutex. Отличие
заключается в том, что Mutex разрешает доступ к ресурсу
только одному потоку (процессу), в то время как Semaphore
разрешает доступ к ресурсам сразу нескольким потокам
(процессам). Количество указывается при создании объекта
Semaphore.
59
60.
Синхронизация потоков (Event)Класс AutoResetEvent является оберткой над объектом ОС
Windows «Event» и позволяет переключить данный объектсобытие из сигнального в несигнальное состояние.
60
61.
Синхронизация потоков (AutoResetEvent)AutoResetEvent notifier = new AutoResetEvent(true);
public void PrintNumbers()
{
notifier.WaitOne();
// . . .
notifier.Set() ;
}
Console.WriteLine();
61
62.
Неблокирующая синхронизация потоковКласс Interlocked позволяет вызывать потокобезопасные
простые атомарные операции с переменными без
использования объектов синхронизации (Monitor, Mutex и
т.д.)
Применение класса Interlocked является гораздо более
быстрым подходом по сравнению с остальными приемами
по обеспечению синхронизации.
62
63.
Неблокирующая синхронизация потоковНекоторые методы класса Interlocked:
Decrement(ref x)
Безопасно уменьшает значение x на 1.
Эквивалентно x--
Exchange(ref x, value)
Безопасно присваивает x значение value.
Эквивалентно x=value
Increment(ref x)
Безопасно увеличивает значение x на 1
Эквивалентно x++
Add(ref x, value)
Безопасно складывает значение x и значение value.
Эквивалентно x+=value
63
64.
Синхронизация потоков (System.Threading.Timer)Класс Timer из пространства имен System.Threading
позволяет запускать метод по истечению заданного
периода времени.
64
65.
Синхронизация потоков (System.Threading.Timer)static void TimerCallBackProc(Object data)
{
Console.WriteLine($"{DateTime.Now.ToLongTimeString()}");
}
Console.WriteLine("***** Timer Starts *****\n");
Timer timer = new Timer(TimerCallBackProc,null,0,1000);
Console.ReadLine();
65
66.
Синхронизация потоков (System.Timers.Timer)Класс Timer из пространства имен System.Timers позволяет
генерировать события по истечению заданного периода
времени.
66
67.
Синхронизация потоков (System.Timers.Timer)using st = System.Timers;
st::Timer timer = new st::Timer(1000);
timer.Elapsed+=(s,e)=>
Console.WriteLine($"{e.SignalTime.ToLongTimeString()}");
Console.WriteLine("***** Timer Starts *****\n");
timer.Start();
Console.ReadLine();
67
68.
StopWatchStopwatch stopWatch = new Stopwatch();
stopWatch.Start();
Thread.Sleep(10000);
stopWatch.Stop();
// Get the elapsed time as a TimeSpan value.
TimeSpan ts = stopWatch.Elapsed;
// Format and display the TimeSpan value.
var
elapsed
=
$"{ts.Hours:00}:{ts.Minutes:00}:{ts.Seconds:00}:{ts.Milliseconds/
10:00}";
Console.WriteLine("RunTime " + elapsed);
https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.stopwatch.-ctor?f1url=%3FappId%3DDev16IDEF1%26l%3DENUS%26k%3Dk(System.Diagnostics.Stopwatch.%2523ctor);k(DevLang-csharp)%26rd%3Dtrue&view=net-5.0
68