Какие проблемы решает Structured Concurrency?

«Какие проблемы решает Structured Concurrency?» — вопрос из категории Многопоточность, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Structured Concurrency — это парадигма, которая организует асинхронные задачи в иерархические структуры, решая ключевые проблемы неструктурированного параллелизма:

  1. Утечки задач и ресурсов — Гарантирует, что все дочерние задачи завершаются до выхода из родительской области видимости (scope).
  2. Отмена (cancellation) — Автоматически распространяет отмену родительской задачи на все дочерние.
  3. Отслеживаемость ошибок — Ошибка в дочерней задаче корректно пробрасывается наверх, а не теряется.
  4. Прозрачность зависимостей — Четко определяет жизненный цикл и отношения между задачами, упрощая отладку.

Пример на Swift:

func fetchAllData(from urls: [URL]) async throws -> [Data] {
    // `withThrowingTaskGroup` создает структурированную область
    try await withThrowingTaskGroup(of: Data.self) { group in
        for url in urls {
            group.addTask {
                // Все эти задачи — дети группы
                try await downloadData(from: url)
            }
        }
        // Группа ожидает завершения ВСЕХ дочерних задач
        var results: [Data] = []
        for try await data in group {
            results.append(data)
        }
        return results
    } // Здесь все задачи гарантированно завершены
}
// Если `fetchAllData` будет отменена, все запущенные `downloadData` также отменятся.

Без Structured Concurrency легко создать "висящие" (orphaned) задачи, которые продолжают выполняться после того, как результат стал не нужен.