Выбор ответа Senior Swift Concurrency обновлено

Реентерабельность акторов

Вопрос

Метод актора проверяет кеш, при промахе делает await download(url) и пишет результат в кеш. Что может пойти не так?

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

Выберите вариант, и откроется разбор.

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

Коротко

Правильный ответ: Во время await актор обслужит другие вызовы, и URL скачается дважды. Акторы в Swift реентерабельны: на каждой точке await актор отпускается и может выполнить другой вызов.

Варианты ответа

  1. Ничего: актор заблокирован до конца метода, включая время ожидания await
  2. Взаимная блокировка: актор ждёт сам себя на await download(url)
  3. Гонка данных на словаре кеша: два потока пишут в него одновременно
  4. Во время await актор обслужит другие вызовы, и URL скачается дваждыправильный ответ

Разбор

Акторы в Swift реентерабельны: на каждой точке await актор отпускается и может выполнить другой вызов. Изоляция защищает от гонок данных (одновременного доступа к словарю), но не от логических гонок: два запроса одного URL оба увидят промах. Решение: хранить в кеше не только результат, но и выполняющуюся Task для URL и отдавать её второму вызывающему. И не полагаться на инварианты, проверенные до await. Взаимной блокировки нет как раз благодаря реентерабельности.

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

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