Wielowątkowość i priorytety

Dzisiaj znów trochę od strony teoretycznej postaram wyjaśnić jak działają priorytety wątków w systemach Windows. Każdy chyba słyszał o tym, że wątkowi można nadać priorytet. Nie każdy natomiast wie, jaki jest zakres oraz jak wygląda dokładnie ich interpretacja.

Przede wszystkim mamy do czynienia z dwoma typami priorytetów, które składają się na końcową wartość używaną przez task scheduler. Pierwszy komponent dotyczy procesu i jest to tzw. klasa priorytetu. W Windows możemy wyróżnić następujące klasy:

 

Nazwa klasy Wartości Domyślna wartość
IDLE_PRIORITY_CLASS 1-6 4
BELOW_NORMAL_PRIORITY_CLASS 4-8 6
NORMAL_PRIORITY_CLASS 6-10 8
ABOVE_NORMAL_PRIORITY_CLASS 8-12 10
HIGH_PRIORITY_CLASS 11-15 13
REALTIME_PRIORITY_CLASS 16-31 24

Wszystkie powyższe klasy dotyczą całego procesu a nie poszczególnego wątku. Domyślnie procesy uruchomione przez Explorer należą do klasy NORMAL_PRIORITY_CLASS. Najwyższa klasa REAL_TIME_PRIORITY przeznaczona jest dla sterowników i innych systemowych programów, które muszą zawsze zostać wykonane i przerywają większość innych wątków. Procesy REAL_TIME mogą przerwać nawet przetwarzanie danych z klawiatury czy z myszki. Z kolei najniższa klasa, IDLE, służy dla programów, które powinny być wykonywane, gdy nie ma nic innego do roboty – np. wygaszacze ekranu.

Z powyższej tabeli również widać, że najwyższy możliwy priorytet to 31.

Drugim komponentem, decydującym o całkowitym priorytecie wątku jest tzw. priorytet relatywny, który dotyczy już specyficznego wątku:

 

Relatywny priorytet Modyfikacja

THREAD_PRIORITY_IDLE

Wartość absolutna:  15 dla realtime, 1 dla dynamic range.

THREAD_PRIORITY_LOWEST

-2

THREAD_PRIORITY_BELOW_NORMAL

-1

THREAD_PRIORITY_NORMAL

0

THREAD_PRIORITY_ABOVE_NORMAL

+1

THREAD_PRIORITY_HIGHEST

+2

THREAD_PRIORITY_TIME_CRITICAL

Wartość absolutna: 31 dla real_time, 15 dla dynamic range

Relatywy priorytet jest zatem przesunięciem względem klasy procesu. Jeśli klasa procesu to HIGH_PRIORITY_CLASS, a relatywny priorytet wątku to THREAD_PRIORITY_BELOW_NORMAL, końcowa wartość będzie równa 13-1==12. Cześć jednak wartości ma charakter absolutny (THREAD_PRIORITY_IDLE oraz THREAD_PRIORITY_TIME_CRITICAL). Końcowa wartość jednak również zależy od klasy procesu. Przedział realtime to wartości od 16-31, a dynamic_range to 1-15.

W systemach Windows istnieje jeszcze priorytet zerowy. Jest on jednak zarezerwowany dla tzw. zero page thread – wątku systemowego używanego do zarządzania pamięcią.

W praktyce, w .NET modyfikujemy wyłącznie relatywny priorytet wątku. .NET nie wspiera najniższego (THREAD_PRIORITY_IDLE) oraz najwyższego relatywnego priorytetu (THREAD_PRIORITY_TIME_CRINICAL). Za pomocą właściwości Thread.Priority możemy ustawić następującą relatywną wartość:

ThreadPriority.Lowest
ThreadPriority.BelowNormal
ThreadPriority.Normal
ThreadPriority.AboveNormal
ThreadPriority.Highest

Należy pamiętać, że scheduler będzie zawsze próbował zaplanować najpierw wątek o wyższym absolutnym priorytecie. Wątki z mniejszym priorytetem będą musiały poczekać aż wszystkie o wyższym zostaną wykonane. Czasami scheduler może samodzielnie zwiększyć priorytet (tzw. priority boost), aby uniknąć na przykład zagłodzenia czy lock convoy – ale o tym kiedyś indziej.

4 thoughts on “Wielowątkowość i priorytety”

  1. A jak to jest przeliczane na priorytety w Linuxie ? Bo tam z tego co pamiętam jest dużo mniej możliwych priorytetów.

Leave a Reply

Your email address will not be published.