Sobes.tech
Middle+

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.