ГЛАВА 18. МНОГОПОТОЧНОЕ ПРОГРАММИРОВАНИЕ |
|
Оглавление |
|
§18.1 Многопоточное программирование ............................................................ |
1 |
§18.1.1 Определение потоков................................................................................. |
1 |
§18.1.2 Пример многопоточности ........................................................................ |
2 |
§18.1.3 Процессы ..................................................................................................... |
3 |
§18.1.4 Классификация потоков в среде .NET Framework ................................. |
3 |
§18.1.5 Цели применения нескольких потоков ..................................................... |
3 |
§18.2 Реализация потоков....................................................................................... |
4 |
§18.2.1 Класс Thread ............................................................................................... |
4 |
§18.2.2 Создание потоков ...................................................................................... |
8 |
§18.2.3 Примеры работы потоков...................................................................... |
10 |
§18.3 Потоки с параметрами ................................................................................ |
13 |
§18.1 Многопоточное программирование
§18.1.1 Определение потоков
Одним из ключевых аспектов в современном программировании является многопоточность. Многопоточность позволяет увеличивать скорость реагирования приложения и, если приложение работает в многопроцессорной или многоядерной системе, его пропускную способность.
Ключевым понятием при работе с многопоточностью является поток.
Поток - основная единица исполнения в операционной системе Windows. Все программы в этой ОС выполняются в потоках. Для того чтобы выполнить код какой-либо программы, ОС сначала создает поток, выделяет для него память,
загружает в нее код программы и только после этого начинается выполнение.
Если говорить простым языком, то поток – это некая независимая последовательность инструкций для выполнения того или иного действия в программе. В одном конкретном потоке выполняется одна конкретная последовательность действий.
1
Совокупность таких потоков, выполняемых в программе параллельно называется многопоточностью программы.
§18.1.2 Пример многопоточности
Для лучшего понимания многопоточности можно представить
следующий пример. Допустим, что наша программа и данные, которые в ней содержатся – это офис с различными предметами (папками, столами,
стульями, ручками), а потоки – это работники данного офиса (изначально у нас только один работник, выполняющий всю работу), и каждый работник занимается теми делами, которые ему было сказано выполнять. Работники могут выполнять одинаковые задания, а могут и различные. В случае выполнения какой-либо одной задачи, несколько работников справятся быстрее, чем один.
Например, если один работник будет собирать шкаф час, то вдвоём они могут управиться уже за полчаса. Однако не стоит переусердствовать в количестве работников (потоков). Математически, если нанять 4 работника, то шкаф соберется за 15 минут, если нанять 60 работников – за 1 минуту, а если нанять 3600, то вообще за секунду, но ведь на деле это неверно. Работники будут только мешать друг другу, толкаться, отнимать друг у друга детали, и
процесс сборки шкафа может затянуться очень надолго.
Так же и с потоками. Чем больше потоков, тем выше вероятность, что они будут мешать друг другу выполнять свою работу. Например, если заставить работать огромное количество потоков с одними и теми же данными, потокам придётся выстраиваться в очередь для их обработки
(например, если тем же 3600 рабочим дать какое-либо письменное задание, но предоставить им для этого дела всего одну ручку, то работникам, естественно,
придётся становиться друг за другом в очередь за ручкой, чтобы после её получения выполнить поставленную задачу. Времени это займёт довольно много).
2
Потоки надо распределять с умом и исключительно в случаях, когда это действительно необходимо для ускорения работы программы либо для повышения производительности.
§18.1.3 Процессы
Потоки в Windows принадлежат процессам. Процесс — это исполнение программы. Операционная система использует процессы для разделения исполняемых приложений.
Программа на C# запускается в единственном потоке, однако процессу может принадлежать множество потоков. Эти потоки могут выполняться одновременно на многопроцессорных системах, что значительно увеличивает производительность программы. В однопроцессорных системах потоки выполняются последовательно, получая по очереди кванты времени (20 мс),
однако даже такое выполнение в некоторых случаях приводит к увеличению производительности программы.
§18.1.4 Классификация потоков в среде .NET Framework
Язык C# имеет встроенную поддержку многопоточности, а среда .NET Framework предоставляет сразу несколько классов для работы с потоками, что в совокупности помогает реализовывать и настраивать многопоточность в проектах.
В среде .NET Framework существует два типа потоков: основной и фоновый (вспомогательный). Фоновые потоки отличаются от основных только в одном аспекте: если первым завершится основной поток, то фоновые потоки в его процессе будут также принудительно остановлены, если же первым завершится фоновый поток, то это не повлияет на остановку основного потока – тот будет продолжать функционировать до тех пор, пока не выполнит всю работу и самостоятельно не остановится.
§18.1.5 Цели применения нескольких потоков
Использовать несколько потоков необходимо, чтобы увеличить скорость реагирования приложения и воспользоваться преимуществами
3
многопроцессорной или многоядерной системы, чтобы увеличить пропускную способность приложения.
Представьте себе классическое приложение, в котором основной поток отвечает за элементы пользовательского интерфейса и реагирует на действия пользователя. Используйте рабочие потоки для выполнения длительных операций, которые, в противном случае будут занимать основной поток, в
результате чего пользовательский интерфейс будет недоступен. Для более оперативной реакции на входящие сообщения или события также можно использовать выделенный поток связи с сетью или устройством.
Если программа выполняет операции, которые могут выполняться параллельно, можно уменьшить общее время выполнения путем выполнения этих операций в отдельных потоках и запуска программы в многопроцессорной или многоядерной системе. В такой системе использование многопоточности может увеличить пропускную способность, а
также повысить скорость реагирования.
§18.2 Реализация потоков
§18.2.1 Класс Thread
Основной функционал для использования потоков в приложении сосредоточен в пространстве имен System.Threading. В нем определен класс, представляющий отдельный поток - класс Thread.
Класс Thread определяет ряд методов и свойств, которые позволяют управлять потоком и получать информацию о нем.
Основные свойства класса Thread описаны в таблице 18.1.
|
Таблица 18.1 – Свойства класса Thread |
|
|
|
|
Наименование свойства |
|
Описание |
|
|
|
|
|
Статическое свойство, которое |
CurrentContext |
|
позволяет получить контекст, в |
|
|
котором выполняется поток |
|
|
|
4
Наименование свойства |
|
Описание |
|
|
|
|
|
|
|
|
Статическое свойство, которое |
CurrentThread |
|
возвращает ссылку на выполняемый |
|
|
|
|
поток |
|
|
|
|
IsAlive |
|
Свойство, которое указывает, |
|
|
работает ли поток в текущий момент |
||
|
|
|
|
|
|
|
|
IsBackground |
|
Свойство, которое указывает, |
|
|
является ли поток фоновым |
||
|
|
|
|
|
|
|
|
Name |
|
Свойство, которое содержит имя |
|
|
потока |
||
|
|
|
|
|
|
|
|
Priority |
|
Свойство, которое хранит приоритет |
|
|
потока1 |
||
|
|
|
|
|
|
|
|
ThreadState |
|
Свойство, которое возвращает |
|
|
состояние потока2 |
||
|
|
|
|
|
|
|
|
Некоторые из методов класса Thread описаны в таблице 18.2. |
|||
|
|
Таблица 18.2 – Методы класса Thread |
|
|
|
|
|
Наименование метода |
|
Описание |
|
|
|
|
|
|
|
|
Статический метод, который |
Sleep |
|
останавливает поток на |
|
|
определенное количество |
||
|
|
|
|
|
|
|
миллисекунд3 |
|
|
|
|
|
|
|
Метод, который уведомляет среду |
|
|
|
CLR о том, что надо прекратить |
Abort |
|
поток, однако прекращение работы |
|
|
потока происходит не сразу, а |
||
|
|
|
|
|
|
|
только тогда, когда это становится |
|
|
|
возможно. Для проверки |
|
|
|
|
|
|
|
|
1https://docs.microsoft.com/ru-ru/dotnet/api/system.threading.threadpriority?view=net-5.0
2https://docs.microsoft.com/ru-ru/dotnet/api/system.threading.threadstate?view=net-5.0
3https://docs.microsoft.com/ru-ru/dotnet/api/system.threading.thread.sleep?view=net-5.0
5