Интерфейс Win32 API позволяет программисту управлять распределением времени между потоками; это распространяется и на приложения, написанные на Delphi. Операционная система планирует время процессора в соответствии с приоритетами потоков.
Приоритет потока — величина, складывающаяся из двух составных частей: приоритета породившего поток процесса и собственно приоритета потока. Когда поток создается, ему назначается приоритет, соответствующий приоритету породившего его процесса.
В свою очередь, процессы могут иметь следующие классы приоритетов.
Примечание
Классы Above normal и Below normal появились впервые в Windows 2000.
Класс реального времени задает приоритет даже больший, чем у многих процессов операционной системы. Такой приоритет нужен для процессов, обрабатывающих высокоскоростные потоки данных. Если такой процесс не завершится за короткое время, пользователь почувствует, что система перестала откликаться, т. к. даже обработка событий мыши не получит времени процессора.
Использование класса High ограничено процессами, которые должны завершаться за короткое время, чтобы не вызвать сбойной ситуации. Пример — процесс, который посылает сигналы внешнему устройству; причем устройство отключается, если не получит своевременный сигнал. Если у вас возникли проблемы с производительностью вашего приложения, было бы неправильно решать их просто за счет повышения его приоритета до high — такой процесс также влияет на всю ОС. Возможно, в этом случае следует модернизировать компьютер.
Большинство процессов запускается в рамках класса с нормальным приоритетом. Нормальный приоритет означает, что процесс не требует какого-либо специального внимания со стороны операционной системы.
И наконец, процессы с фоновым приоритетом запускаются лишь в том случае, если в очереди Диспетчера задач нет других процессов. Обычные виды приложений, использующие такой приоритет, — это программы сохранения экрана и системные агенты (system agents). Программисты могут использовать фоновые процессы для организации завершающих операций и реорганизации данных. Примерами могут служить сохранение документа или резервное копирование базы данных.
Приоритеты имеют значения от 0 до 31. Процесс, породивший поток, может впоследствии изменить его приоритет; в этой ситуации программист имеет возможность управлять скоростью отклика каждого потока.
Базовый приоритет нити складывается из двух составляющих, однако это не означает, что он просто равен их сумме. Взгляните на соответствующие величины, которые показаны в табл. 29.1. Для потока, имеющего собственный приоритет THREAD_PRIORITY_IDLE, базовый приоритет будет равен 1, невзирая на приоритет породившего его процесса.
И еще для класса Normal приведены по два приоритета, снабженные буквами В (Background) и F (Foreground). Объяснение этому дается ниже.
Таблица 29.1. Классы процессов и приоритеты их потоков (для Windows 2000 и ХР)
IDLE_ PRIORITY CLASS |
BELOW_ NORMAL PRIORITY CLASS |
NORMAL_ PRIORITY_ CLASS |
ABOVE_ NORMAL_ PRIORITY_ CLASS |
HIGH PRIORITY CLASS |
REALTIME PRIORITY CLASS |
|
THREAD_ PRIORITY_ IDLE |
1 |
1 |
1 |
1 |
1 |
16 |
THREAD_ PRIORITY LOWEST |
2 |
4 |
5(B) 7(F) |
8 |
11 |
22 |
THREAD_ PRIORITY_ BELOW NORMAL |
3 |
5 |
6(B) 8(F) |
9 |
12 |
23 |
THREAD_ PRIORITY_ NORMAL |
4 |
6 |
7(B) 9(F) |
10 |
13 |
24 |
THREAD PRIORITY_ ABOVE_ NORMAL |
5 |
7 |
8(В) 10(F) |
11 |
14 |
25 |
THREAD_ PRIORITY_ HIGHEST |
6 |
8 |
9(B) 11(F) |
12 |
15 |
26 |
THREAD_ PRIORITY TIME CRITICAL |
15 |
15 |
15 |
15 |
15 |
31 |
Помимо базового приоритета, описываемого в этой таблице, планировщик заданий (scheduler) может назначать так называемые динамические приоритеты. Для процессов класса NORMAL_PRIORITY_CLASS при переключении из фонового режима в режим переднего плана и в ряде других случаев приоритет потока, с которым создано окно переднего плана, повышается. Так работают все клиентские операционные системы от Microsoft. Серверные операционные системы оптимизированы для выполнения фоновых приложений. Впрочем, Windows NT и более поздние ОС на этом ядре позволяют переключать режим оптимизации, используя переключатель Application response апплета System панели управления Windows (рис. 29.1).
К тому же Windows 2000 Professional и Windows 2000 Server имеют разные алгоритмы выделения квантов времени. Первая — клиентская — операционная система выделяет время короткими квантами переменной длины для ускорения реакции на приложения переднего плана (foreground). Для сервера же более важна стабильная работа системных служб, поэтому во второй ОС система распределяет длинные кванты постоянной длины.
Рис. 29.1. С помощью диалога Performance Options можно управлять алгоритмом назначения приоритетов
Теперь, разобравшись в приоритетах потоков, нужно обязательно сказать о том, как же их использует планировщик заданий для распределения процессорного времени.
Операционная система имеет различные очереди готовых к выполнению потоков — для каждого уровня приоритета свой. В момент распределения нового кванта времени она просматривает очереди — от высшего приоритета к низшему. Готовый к выполнению поток, стоящий первым в очереди, получает этот квант и перемещается в хвост очереди. Поток будет исполняться всю продолжительность кванта, если не произойдет одно из двух событий:
Теперь, наверное, вам более ясна опасность, исходящая от неоправданного завышения приоритетов. Ведь, если есть активные потоки с высоким приоритетом, ни один поток с более низким приоритетом ни разу не получит времени процессора. Эта проблема может подстерегать вас даже на уровне вашего приложения. Предположим, вы назначили вычислительному потоку приоритет THREAD_PRIORITY_ABOVE_NORMAL, а потоку, где обрабатывается ввод пользователя, — THREAD_PRIORITY_BELOW_NORMAL. Тогда вместо запланированного результата — совместить вычисления с нормальной реакцией приложения — вы получите строго обратный. Приложение вообще перестанет откликаться на ввод, и снять его будет возможно только с помощью средств ОС.
Так что нормальная практика для асимметричных потоков — это назначение потоку, обрабатывающему ввод, более высокого приоритета, а всем остальным — более низкого или даже приоритета idle, если этот поток должен выполняться только во время простоя системы.