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.
A jak to jest przeliczane na priorytety w Linuxie ? Bo tam z tego co pamiętam jest dużo mniej możliwych priorytetów.
O Linuxie niestety nie mam pojecia:)
Malutki błąd: “końcowa wartość będzie równa 13-1==14”. Pozdrawiam.
@Rosiu:
Haha, dzieki, glupi blad:)