Приоритеты потоков
Помимо базового приоритета, описываемого в этой таблице, планировщик заданий (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, если этот поток должен выполняться только во время простоя системы.