5. Task Priority
Изучение данного блока предполагает предварительное знание синтаксиса языка Swift. Для успешного освоения этого материала, необходимо иметь базовое понимание синтаксиса языка Swift. Это включает в себя знание основных структур данных, операторов, циклов, функций, абстракций и других ключевых элементов языка. Без этих фундаментальных знаний будет сложно понять более сложные концепции и примеры, которые будут рассматриваться в данном блоке.
Приоритеты имеют важную роль в построении задач. Эта роль намного важнее, чем выставление qos в GCD.
Priority Inversion¶
Инверсия приоритетов - это одна из проблем многопоточности. Заключается она в том, что задача с высоким приоритетом ждёт пока выполняются задачи с низким приоритетом.
В Structured Concurrency мы постоянно переключаемся между состояниями, при каждом вызове ключевого слова await мы отдаём поток исполнителю и он запускает следующую задачу. В этот промежуток времени исполнитель определяет следующую задачу на исполнение, учитывая её приоритет. Благодаря такому механизму работы мы можем лучше работать с проблемой Priority Inversion
Поэтому когда мы работаем с задачами, нужно всегда помнить про приоритет задач и определять их правильно. Также не нужно выставлять у всех задач самый высокий приоритет. Дочерние задачи автоматически наследуют приоритет родительской задачи.
Виды приоритетов¶
- background/utility
- low
- medium
- high
- userInitiated
Обратите внимание
Когда вы используете модифаер .task для view в SUI - по умолчанию выставляется приоритет - userInitiated.
Если мы инициализируем 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 }