Cамоучитель по Visual Studio.Net

       

Процессы и потоки



Процессы и потоки

Различают два способа реализации многозадачности:

  • создать один процесс, имеющий несколько потоков выполнения (threads);
  • создать несколько процессов, каждый из которых имеет один или несколько потоков выполнения.

Многозадачная (multi-process) система позволяет двум или более программам выполняться одновременно. Многопотоковая (multi-threaded) система позволяет одной программе выполнять сразу несколько потоков одновременно. Современные операционные системы сочетают в себе оба эти свойства. Приложение Win32 может состоять из одного или более процессов. Например, приложение по расчету параметров турбогенератора может состоять из удобной оболочки, написанной на языке C++ (главный процесс), и вычислительных модулей, написанных на языке FORTRAN и запускаемых в виде отдельных (порожденных) процессов. При этом возможен вариант, когда один процесс (модуль программы) занят выводом геометрии расчетной области, а другой одновременно производит расчет электромагнитного поля.

Процесс — это понятие, относящееся к операционной системе. Каждый раз, как вы запускаете приложение, система создает и запускает новый процесс. Процесс можно грубо отождествить с ехе-кодом, выполняющимся в отдельном процессоре. С каждым процессом система связывает такие ресурсы, как:

  • виртуальное адресное пространство;


  • исполнимый код и данные;
  • базовый приоритет;
  • описатели объектов;
  • переменные окружения.

Windows NT/2000 отводит для каждого процесса виртуальное адресное пространство в 4 Гбайт, защищенное от других процессов, которые выполняются в системе в то же самое время.

Каждый процесс обязательно создает первичный поток (primary thread) выполнения. Он делает это автоматически и, если программист не предпринимает каких-либо специальных усилий по созданию второго потока, то первичный поток и породивший его процесс обычно отождествляются в сознании пользователя, а , часто и в сознании программиста. Но последний может создать еще один или несколько потоков, которые размещаются в одном и том же адресном пространстве, принадлежащем процессу. Когда они создаются, родительский процесс начинает выполняться не последовательно, а параллельно. Так реализуется потоковая многозадачность. Говорят, что потоки выполняются в контексте процесса.

Поток (thread) — это основной элемент системы, которому ОС выделяет машинное время. Поток может выполнять какую-то часть общего кода процесса, в том числе и ту часть, которая в это время уже выполняется другим потоком. Например, код функции, отображающей на экране степень продвижения процесса передачи информации, может одновременно выполняться двумя потоками, которые обслуживают двух клиентов одного сервера.

Примечание
Примечание

Сравнительно недавно появилось еще несколько терминов, связанных с этой же тематикой. Нитью (fiber) потока называется выполняемый блок кодов, который «вручную» (manually) прерывается или планируется (scheduled) приложением. Нить выполняется в контексте потока, который ее планирует. Заданием (job object) называется группа процессов, объединенных в общий блок (unit). Задание в ОС имеет свое имя, атрибуты защиты и способность управлять общими (разделяемыми) ресурсами. Операции, производимые системой или программистом над заданиями, воздействуют на все составляющие его процессы.

Все потоки (threads) одного процесса пользуются ресурсами породившего их процесса. Кроме того, каждому потоку система и/или программист приписывает приоритет выполнения и набор структур языка С, описывающих контекст потока. Система использует их для запоминания контекста потока, когда его выполнение прерывается. В контекст входят:

  • состояние регистров;
  • системный стек ядра ОС (kernel stack);
  • стек пользователя (user stack), расположенный в адресном пространстве процесса;
  • блок переменных окружения потока.

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

  • управление вводом в различные документы МШ-интерфейса. Ввод данных каждого документа приложения организован в виде отдельного потока;
  • управление вводом данных из нескольких устройств телекоммуникации;
  • разграничение приоритетов выполнения задач. Потокам, требующим высокой скорости реакции, присваивается высокий приоритет, а другим потокам более низкий;
  • снижение времени реакции на действия пользователя по вводу данных при одновременном выполнении фоновых вычислений.

Обычно более эффективной является реализация многозадачности в виде одного процесса с несколькими потоками, чем в виде многих процессов с одним потоком, так как:

  • контексты потоков занимают меньший объем, чем контексты процессов и система переключает их быстрее;
  • взаимодействие потоков проще, так как они могут пользоваться глобальными переменными в общем для них адресном пространстве процесса;
  • потоки одного процесса легче синхронизировать, так как им доступны описатели объектов ядра из общего контекста процесса.

Если один поток выполняет медленные операции ввода-вывода, а другой выполняет вычисления, используя только процессор, то эффективность процесса, совмещающего два потока, будет значительно выше, чем эффективность двух процессов, выполненных последовательно. Типичным многопотоковым приложением является сервер, обслуживающий многих пользователей. Каждый новый пользователь обслуживается отдельным потоком одного процесса. Вместо ожиданий, которые связаны с дисковыми операциями, система может перейти к выполнению другого потока.

Однако в случае ошибочного проектирования потоки могут и ухудшить общий показатель эффективности процесса. Например, время выполнения процесса с двумя потоками будет ниже, чем эффективность двух последовательных однопо-токовых процессов, если оба потока выполняются в памяти и не требуют интерфейса с пользователем. Система вынуждена постоянно прерывать эффективно работающие потоки и переключаться между ними. Эти переключения ведут к ненужным потерям или лишним операциям (overheads) по загрузке в память и последующей выгрузке структур данных, необходимых для обслуживания потоков. Наличие пользовательского интерфейса приводит к тому, что указанные действия выполняются во время неизбежных пауз, связанных с операциями ввода-вывода, что создает иллюзию совмещения во времени.

Создание многопотоковых процессов требует тщательного предварительного анализа с тем, чтобы должным образом скоординировать действия операционной системы и других программных компонентов. Отслеживание состояний многочисленных потоков требует значительных временных затрат, поэтому следует помнить, что Win32-API предоставляет и другие средства реализации асинхронное™ выполнения операций. Например: асинхронный ввод-вывод (I/O), специальные порты I/O (completion ports), асинхронные вызовы удаленных процедур (asynchronous procedure calls — АРС), функции ожидания системных событий (wait functions).

Совместный доступ потоков к разделяемым ресурсам: описателям файлов, портов, глобальным переменным, может создать конфликты. Например, один поток читает данные, а другой пытается одновременно их изменить или один поток ждет завершения определенной операции другим потоком, а тот, в свою очередь, ждет отработки первого потока. Такое зацикливание называется тупиковой ситуацией (deadlock). Для предупреждения конфликтов такого рода существуют специальные синхронизирующие объекты ядра системы:, семафоры, мьютексы, события.



Содержание раздела