Проблемы многопоточной архитектуры

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

Основные понятия

Процесс (process) – это отдельная исполняемая программа с используемой ею памятью и другими выделяемыми ей ресурсами. Многозадачность (multitasking) - это способность операционной системы выполнять несколько программ одновременно. В основе этого принципа лежит использование операционной системой аппаратного таймера для выделения отрезков времени (time slices) для каждого из одновременно выполняемых процессов.

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

32-разрядные версии Windows кроме многозадачности поддерживают еще и многопоточность (multithreading). Многопото́чность - способ выполнения процесса, при котором вычисления разбиваются на несколько потоков, выполняющихся «параллельно», т.е. без предписанного порядка во времени. При выполнении некоторых задач такое разделение может достичь более эффективного использования ресурсов вычислительной машины.

Все потоки выполняются в адресном пространстве процесса

  • Поток (thread) – это последовательность исполняемых команд. Процесс может состоять из единственного потока, а может содержать их несколько

Итак,

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

В Win32, не процесс и не задача, а именно поток является базовым элементом механизма выполнения программ.

К достоинствам многопоточности в программировании можно отнести следующее:

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

Повышение производительности процесса за счет распараллеливания процессорных вычислений и операций ввода/вывода.

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

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

Основным фактором, учитываемым при диспетчеризации, служит приоритет выполнения (execution priority) каждого потока. В Win32 каждому потоку присваивается свой приоритет - от 0 до 31; чем больше число, тем выше приоритет. Приоритет 31 резервируется под особенно критичные операции, например, прием данных в реальном режиме времени. Приоритет 0 назначается операционной системой самым второстепенным задачам, выполнение которых происходитв то время, когда нет других задач. Большинство потоков работают с приоритетом от 7 до 11.

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

Проблемы многопоточной архитектуры

Приведем рекомендации по архитектуре многопоточных программ.

· Рекомендуется, чтобы первичный или главный (primary) поток программы создавал все окна и соответствующие им оконные процедуры, необходимые в программе, и обрабатывал все сообщения для этих окон.

· Всеостальные потоки должны быть вторичными (secondary), выполняющими фоновые задачи и не имеющими интерактивной связи с пользователем, кроме как через первичный поток.

Рассмотрим проблему разделения ресурсов.

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

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

· Однако у каждого потока есть свой собственный стек, и значит, автоматические переменные являются уникальными для каждого потока.

· Каждый поток, также, имеет свое состояние процессора, которое сохраняется и восстанавливается при переключении между потоками.

Итак,

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

· Автоматические переменные функций потоков (которые являются локальными по отношению к функции) - уникальны для каждого потока, т.к. они располагаются в стеке, а каждый поток имеет свой стек.

· Иногда бывает удобно использовать для двух и более потоков одну и ту же функцию, а статические данные использовать уникальные для каждого потока. Для каждого потока можно выделитьспециальную, локальную для него память, недоступную для других потоков.

Разработка, программирование и отладка сложного многопоточного приложения являются, естественно, самыми сложными задачами, с которыми приходится сталкиваться Windows-программисту.

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

· Одной из основных ошибок в многопоточных программах является так называемое состояние гонки (race condition). Это случается, если программист считает, что один поток закончит выполнение своих действий, например, подготовку каких-либо данных, до того, как эти данные потребуются другому потоку.