Решение 11 распространенных проблем в многопоточном коде - Инверсия приоритета
ОГЛАВЛЕНИЕ
Инверсия приоритета
Изменение приоритета потоков обычно является поиском неприятностей. Инверсия приоритета может произойти, когда многие потоки с различным приоритетом имеют общий доступ к одним и тем же блокировкам и ресурсам, и поток с низким приоритетом практически до бесконечности задерживает работу потока с более высоким приоритетом. Мораль этой истории – просто избегайте изменений приоритетов потоков насколько это возможно.
Вот крайний пример инверсии приоритета. Представьте себе, что поток ThreadA с низким приоритетом получает блокировку L. Затем появляется поток ThreadB, имеющий высокий приоритет. Он пытается получить L, но не может, поскольку ее удерживает ThreadA. Это и есть «инверсия»: дело обстоит так, как если бы потоку ThreadA был искусственно и временно дан больший приоритет, чем у потока ThreadB, просто потому, что он удерживает блокировку, необходимую потоку ThreadB.
Эта ситуация со временем разрешится сама собой, когда поток ThreadA освободит блокировку. Увы, это еще не все – представьте, что произойдет, когда на сцене появится поток ThreadC со средним приоритетом. Хотя поток ThreadC не нуждается в блокировке L, его простое присутствие может полностью исключить выполнение потока ThreadA, что непрямым образом предотвратит выполнение высокоприоритетного потока ThreadB.
Рано или поздно эта ситуация будет замечена потоком диспетчера установки баланса Windows Balance Set Manager. Даже если поток ThreadC останется работоспособным навсегда, поток ThreadA со временем (через четыре секунды) получит временное повышение приоритета от ОС. Остается надеяться, что этого достаточно, чтобы он довел работу до завершения и освободил блокировку. Но задержка здесь огромна (четыре секунды), и если с этим связан какой-либо интерфейс пользователя, пользователь приложения наверняка заметит проблему.