Акторы в Swift: изоляция и реентерабельность
Вопрос
Расскажите, как работают акторы и какие у них подводные камни.
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Актор сериализует доступ к своему состоянию, снаружи `await`
Реентерабельность: на `await` внутри метода выполняются другие вызовы
Инварианты нельзя проверять до `await` и использовать после
Слияние одинаковых запросов через хранение `Task` в акторе
`nonisolated` для методов без доступа к состоянию, `@MainActor` для UI
Глобальные акторы и переходы между доменами имеют цену (hop)
Что могут спросить следом
- Почему акторы сделали реентерабельными, а не блокирующими?
- Что такое
isolatedпараметр?
Разбор
Актор это ссылочный тип, чьё изменяемое состояние доступно только изнутри: методы выполняются по одному на его executor, поэтому гонок данных нет. Снаружи любое обращение асинхронное, через await. Главный подвох это реентерабельность: если метод актора делает await, актор отпускается и может выполнять другие вызовы. Значит, всё, что я проверил до await, после него может быть неверно. Пример: кеш картинок, два запроса одного URL оба видят промах и оба качают. Решение: класть в словарь саму Task до await, и второй вызов дождётся её. Акторы сделали реентерабельными, чтобы не было взаимных блокировок. Методы, не трогающие состояние, помечаю nonisolated. И помню, что каждый переход между акторами, например с главного на свой и обратно, это переключение контекста, поэтому не дроблю работу на сотни мелких вызовов актора.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.