Ответ вслух Senior Swift Concurrency обновлено

Акторы в Swift: изоляция и реентерабельность

Вопрос

Расскажите, как работают акторы и какие у них подводные камни.

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Актор это ссылочный тип, чьё изменяемое состояние доступно только изнутри: методы выполняются по одному на его executor, поэтому гонок данных нет. Снаружи любое обращение асинхронное, через await.

Что должно прозвучать в ответе

  • Актор сериализует доступ к своему состоянию, снаружи `await`

  • Реентерабельность: на `await` внутри метода выполняются другие вызовы

  • Инварианты нельзя проверять до `await` и использовать после

  • Слияние одинаковых запросов через хранение `Task` в акторе

  • `nonisolated` для методов без доступа к состоянию, `@MainActor` для UI

  • Глобальные акторы и переходы между доменами имеют цену (hop)

Что могут спросить следом

  • Почему акторы сделали реентерабельными, а не блокирующими?
  • Что такое isolated параметр?

Разбор

Актор это ссылочный тип, чьё изменяемое состояние доступно только изнутри: методы выполняются по одному на его executor, поэтому гонок данных нет. Снаружи любое обращение асинхронное, через await. Главный подвох это реентерабельность: если метод актора делает await, актор отпускается и может выполнять другие вызовы. Значит, всё, что я проверил до await, после него может быть неверно. Пример: кеш картинок, два запроса одного URL оба видят промах и оба качают. Решение: класть в словарь саму Task до await, и второй вызов дождётся её. Акторы сделали реентерабельными, чтобы не было взаимных блокировок. Методы, не трогающие состояние, помечаю nonisolated. И помню, что каждый переход между акторами, например с главного на свой и обратно, это переключение контекста, поэтому не дроблю работу на сотни мелких вызовов актора.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.