Что такое многопоточный и асинхронный код в Swift
Что проверяют
Различаете ли вы две разные вещи, которые в речи часто сливают: параллельное выполнение на нескольких потоках и асинхронное ожидание без блокировки потока. Дальше почти всегда идёт продолжение про обновление интерфейса и про гонки, так что ответ заодно показывает, писали ли вы что-то сложнее учебного запроса.
Как отвечать
Многопоточность отвечает на вопрос, где исполняется код: несколько потоков, реально одновременная работа на разных ядрах. Асинхронность отвечает на вопрос, как код ждёт: во время ожидания сети задача освобождает поток, а не держит его. Одно без другого возможно.
Классический инструмент это очереди диспетчеризации: фоновая работа уходит на глобальную очередь с нужным качеством обслуживания, результат возвращается на главную. Современный способ короче и безопаснее.
@MainActor
final class FeedModel: ObservableObject {
@Published private(set) var items: [Item] = []
func reload() async throws {
async let top = api.top()
async let recent = api.recent()
items = try await top + recent
}
}Назовите структурированную конкурентность: дочерние задачи живут не дольше родителя, отмена распространяется вниз, группы задач дают контролируемый параллелизм. Защита разделяемого состояния это актор, а привязка к главному потоку выражается атрибутом, а не ручным возвратом на очередь.
Где спотыкаются
Считают, что await сам по себе даёт параллельность. Два ожидания подряд выполняются последовательно, и чтобы запросы пошли одновременно, нужен async let или группа задач.
Обновляют интерфейс из фонового контекста. Падения при этом плавающие, воспроизводятся через раз, и найти их без включённой проверки главного потока трудно.
Смешивают старый и новый подходы и блокируют поток кооперативного пула семафором или синхронным вызовом внутри асинхронной функции. Потоков в пуле примерно по числу ядер, и несколько таких блокировок останавливают всю конкурентную работу приложения.