Приоритеты имеют важную роль в построении задач. Эта роль намного важнее, чем выставление qos в GCD.
Инверсия приоритетов - это одна из проблем многопоточности. Заключается она в том, что задача с высоким приоритетом ждёт пока выполняются задачи с низким приоритетом.
В Structured Concurrency мы постоянно переключаемся между состояниями, при каждом вызове ключевого слова await мы отдаём поток исполнителю и он запускает следующую задачу. В этот промежуток времени исполнитель определяет следующую задачу на исполнение, учитывая её приоритет. Благодаря такому механизму работы мы можем лучше работать с проблемой Priority Inversion
Поэтому когда мы работаем с задачами, нужно всегда помнить про приоритет задач и определять их правильно. Также не нужно выставлять у всех задач самый высокий приоритет. Дочерние задачи автоматически наследуют приоритет родительской задачи.
Обратите внимание
Когда вы используете модифаер .task для view в SUI - по умолчанию выставляется приоритет - userInitiated
Если мы инициализируем Task/Task.detched без указания приоритета, то приоритет по умолчанию nil, а он приравнивается к самому низкому приоритету - нулевому.
Код из сорцов swift bits |= (bits & ~0xFF) | Int(priority?.rawValue ?? 0)
В некоторых ситуациях приоритет задачи повышается — то есть задача обрабатывается так, как если бы она имела более высокий приоритет, но фактически приоритет не меняется
Если задача 1 выполняется на Actor и на выполнение к Actor приходит задача 2 с более высоким приоритетом, то исполняемая задача 1 временно получает приоритет задачи 2.
Если задача с более высоким приоритетом вызывает метод value, то приоритет этой задачи увеличивается до тех пор, пока она не завершится.
Task(priority: .high) {
print("Задача запущена с высоким приоритетом")
/// Задача запустится с низким приоритетом,
/// но из-за вызова value её приоритет будет увеличен до high
await Task(priority: .low) { }.value
}