TGViewer
Евгений Козлов пишет про IT Евгений Козлов пишет про IT @careerunderhood · 2.84K subscribers
Post #437 1.53K
Concurrency, Synchronization and Consistency. Пост № 23. Priority Inversion или баг случившийся на Марсе (реально)

Что-то я увлекся рассказами про мьютексы и совсем забыл что не довел рассказ про планирование потоков и приоритеты до конца. Возвращаю должок, рассмотрим интересную задачу из реальной жизни.

🔵 Ситуация
У нас есть 3 потока и каждому назначена своя задача (псевдокод для простоты):
Thread L (low priority):
lock(mutex)
do_some_work()
unlock(mutex)

Thread H (high priority):
lock(mutex)
critical_work()
unlock(mutex)

Thread M (medium priority):
while true:
do_cpu_work()

Что происходит:
- L стартует первым -> захватывает mutex
- H стартует вторым -> пытается захватить mutex -> блокируется, ждёт L
- M стартует третьим -> вытесняет L (приоритет выше) -> крутится на CPU

Итог:
- L не получает CPU, не может освободить mutex.
- H ждёт L, но L вытеснен M.

Следствие: Неэффективная работа программы. Как вы уже поняли из названия эта ситуация и есть инверсия приоритетов - проблема в многозадачных системах, когда задача с высоким приоритетом вынуждена ждать выполнения задачи с низким приоритетом, владеющей необходимым ей ресурсом (мьютексом).

На первый взгляд выглядит странно. В обычных задачах на работе нам не нужно знать про приоритеты потоков. Плюс вытесняющий планировщик выручает переключая контекст и выделяя всем время поработать. Вроде проблема, а вроде и нет🙂

Ответ: Если бы такая ситуация случилась на каком нибудь устройстве от которого ожидают работы в реальном времени то это могла бы быть катастрофа. И такие провалы имеют место в реальности, например на Марсе в 1997м году. Рассказывать долго не хочу, советую статью на хабре с иллюстрациями и контекстом.

🔵 Как разрешить Priority Inversion?

1️⃣ Запрет прерываний в критических секциях

Первое что приходит в голову - запретить прерывать поток находящийся в критической секции (помним что у нас вытесняющее планирование и ОС может прервать поток в любой момент). Но доступна такая магия только в kernel space, поэтому и используется трюк обычно:
- В драйверах для атомарного доступа к hardware registers.
- В критических секциях ядра, чтобы избежать прерывания и race conditions.

Нам нужны механизмы влияния в user-space, поэтому идем дальше.

2️⃣ Протокол пороговых приоритетов (priority ceiling protocol, PCP)

- Каждый mutex имеет "потолочный приоритет" - максимальный приоритет всех потоков, которые могут его захватить.
- Когда поток захватывает такой mutex его приоритет временно повышается до потолка mutex. Это предотвращает вытеснение потока средними по приоритету задачами.
- Когда поток освобождает mutex приоритет возвращается к исходному.

Реализация в POSIX:
pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_PROTECT);


3️⃣Протокол наследования приоритетов (priority inheritance protocol, PIP)


Когда H ждёт mutex, который удерживает L:
- L временно получает приоритет H, пока не освободит mutex.
- После unlock приоритет L возвращается к исходному.

Реализация в POSIX:
pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);


🔵 Что выбрать, PIP или PCP?

- PIP защищает от priority inversion, но допускает deadlock. Довольно просто реализуется, есть везде.
- PCP более строгий, предсказуемый, предотвращает priority inversion и deadlock. Его основной минус - избыточное повышение приоритета. Сложнее в реализации и поддержке.

В реальной жизни используют PIP для стандартных приложений на Linux/RTLinux и PCP для safety-critical embedded или RTOS.

—————

Фух, думаю на этом остановиться. Основные проблемы Concurrency (Deadlock, Race Condition, Readers-Writers, Busy Waiting, Priority Inversion) в рамках цикла постов мы рассмотрели.

Осталось несколько тем и цикл можно завершать. Спасибо что читали, буду рад вашим реакциям и комментариям!

📖 Оглавление
  • 🔥 14
  • 👍 4
More from @careerunderhood
  1. Oct 2, 2026Пока от темы Concurrency далеко не ушли. В последнем цикле я если и упоминал вопросы произ…
  2. Sep 30, 2026Результаты опроса меня впечатлили. Большинству интересны истории из работы. Поехали, начне…
  3. Sep 25, 2026Post #470
  4. Sep 21, 2026Concurrency, Synchronization and Consistency. Non-blocking. Оглавление Введение - Блокирую…
  5. Sep 21, 2026Concurrency and Consistency. Non-blocking, lock-free and async. Пост №12. Заключение. Когд…
  6. Sep 20, 2026Concurrency and Consistency. Non-blocking, lock-free and async. Пост №11. Самые важные фак…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →