Jak może się zdarzyć sytuacja, w której kolej o niższym priorytecie uzyskuje dostęp do zasobów wcześniej niż kolej o wyższym priorytecie?
sobes.tech AI
Odpowiedź od AI
To może się zdarzyć z powodu inwersji priorytetów.
Inwersja priorytetów występuje, gdy zadanie o niskim priorytecie utrzymuje zasób (np. mutex), który jest potrzebny zadaniu o wysokim priorytecie. Zadanie o wysokim priorytecie jest zablokowane, oczekując na zwolnienie zasobu. Jednocześnie zadanie o średnim priorytecie może zostać wyprzedzone przez inne zadanie, które nie potrzebuje tego zasobu. W rezultacie zadanie o średnim priorytecie wykonuje się, podczas gdy zadanie o niskim priorytecie, które utrzymuje zasób, i zadanie o wysokim priorytecie, które jest zablokowane, czekają. W rzeczywistości zadanie o wysokim priorytecie czeka na zwolnienie zasobów przez zadania o średnim i niskim priorytecie.
Rozwiązania problemu inwersji priorytetów:
- Dziedziczenie priorytetów (Priority Inheritance): Gdy zadanie o niskim priorytecie utrzymuje zasób potrzebny zadaniu o wysokim priorytecie, tymczasowo przypisuje mu się priorytet zadania o wysokim priorytecie. Po zwolnieniu zasobu priorytet wraca do pierwotnego.
- Protokół najwyższego priorytetu (Priority Ceiling Protocol): Każdemu zasobowi przypisuje się "sufit priorytetu" — najwyższy priorytet spośród wszystkich zadań, które mogą korzystać z tego zasobu. Zadanie może uzyskać dostęp do zasobu tylko wtedy, gdy jego bieżący priorytet jest wyższy niż sufity priorytetów wszystkich zajętych zasobów w danym momencie (w tym tych, które już utrzymuje).
Na iOS, Grand Central Dispatch (GCD) i Operation Queues mają mechanizmy minimalizujące inwersję priorytetów, ale w skomplikowanych scenariuszach z blokadami, takie sytuacje mogą nadal wystąpić, jeśli są używane nieprawidłowo.