Наверх Системное программирование
Предыдущий раздел Оглавление Следующий раздел

3.2.2. Классическая модель потоков

Добавление к модели процесса потоков делает возможным реализацию нескольких независимых друг от друга выполняемых задач в единой среде процесса. Потоки называют иногда облегченными процессами из-за имеющихся между понятиями потока и процесса сходств. Например, если потоки параллельно выполняются в рамках одного процесса, то процессы – в рамках одной вычислительной системы. Если потоки используют единое адресное пространство процесса и другие его ресурсы, то процессы – общую физическую память, диски, принтеры и другие ресурсы вычислительной системы. Для описания работы нескольких потоков в рамках одного и того же процесса используется термин «многопоточный режим».

На рис. 3.6, а показаны три обычных процесса. Каждый из них имеет собственное адресное пространство и один поток управления. А на рис. 3.6, б показан один процесс, у которого есть сразу три потока управления. При равном в каждом из случаев количестве потоков между ними имеются существенные различия. На рис. 3.6, а каждый из потоков выполняется в собственном адресном пространстве, а на рис. 3.6, б все потоки используют общее адресное про¬странство процесса.

Рис

Рис. 3.6. Три процесса, у каждого из которых
есть один поток выполнения(а);
один процесс с тремя потоками(б)

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

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

3.3. Использование объектов потоками
Элементы, присущие каждому процессу Элементы, присущие каждому потоку
Адресное пространство Счетчик команд
Глобальные переменные Регистры
Открытые файлы Стек
Дочерние процессы Состояние
Необработанные аварийные сигналы
Сигналы и обработчики сигналов
Учетная информация

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

У каждого потока есть собственный стек (рис. 3.7). По аналогии с процессом стек каждого по¬тока содержит по одному участку для каждой вызванной процедуры. Такой участок будет содержать и локальные переменные подпрограммы, и адрес возврата управления по завершении работы подпрограммы. Среда выполнения одного потока будет отличаться от сред выполнения других потоков в основном за счет вызовов различных процедур.

Рис

Рис. 3.7. Каждый поток имеет
собственный стек

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

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

Еще одним распространенным системным вызовом, осуществляемым потоком, является thread_yield, который позволяет потоку добровольно освободить центральный процессор для того, чтобы началось выполне¬ние другого потока. Данный системный вызов важен при выполнении потоков по той причине, что при планировании потоков нет возможности использовать прерывания по таймеру. Другие системные вызовы позволяют одному потоку ожидать завершения работы другого потока, а этому потоку дают возможность оповестить другие потоки о завершении определенной работы и т.д.

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

Предыдущий раздел Оглавление Следующий раздел