Ответ
GCD (Grand Central Dispatch) — низкоуровневый C-API для управления потоками через очереди. async/await — высокоуровневая абстракция Swift Concurrency для асинхронного программирования.
Сравнительная таблица:
| Аспект | GCD | async/await |
|---|---|---|
| Уровень абстракции | Низкий (потоки, очереди) | Высокий (задачи, продолжения) |
| Синтаксис | Closures, callback hell | Последовательный код с await |
| Управление потоками | Ручное (DispatchQueue.main/global) |
Автоматическое (cooperative pool) |
| Отмена задач | DispatchWorkItem.cancel() |
Task.cancel(), проверка Task.isCancelled |
| Обработка ошибок | Через completion handlers | Встроенная через throw/try/catch |
| Приоритеты | QoS (.userInteractive, .background) | TaskPriority (.high, .medium, .low) |
| Состояние гонки | Возможно без синхронизации | Предотвращается через Actors |
Пример GCD:
func fetchData(completion: @escaping (Result<Data, Error>) -> Void) {
DispatchQueue.global(qos: .userInitiated).async {
let data = // ... загрузка
DispatchQueue.main.async {
completion(.success(data))
}
}
}
Пример async/await:
func fetchData() async throws -> Data {
// Автоматически выполняется в background pool
let data = try await downloadFromNetwork()
return data
}
// Использование:
Task {
do {
let data = try await fetchData()
await MainActor.run {
updateUI(with: data) // Автоматически на главном потоке
}
} catch {
handleError(error)
}
}
Ключевые преимущества async/await:
- Читаемость — линейный код вместо вложенных closures
- Безопасность — интеграция с Actors для потокобезопасности
- Производительность — cooperative threads вместо создания потоков
- Интеграция — работа с
@MainActor,TaskGroup,AsyncSequence
Когда использовать GCD:
- Низкоуровневый контроль над потоками
- Работа с legacy кодом
- Таймеры (
DispatchSourceTimer) - Барьеры для чтения/записи
Ответ 18+ 🔞
Вот смотри, блядь, сейчас мы разберёмся, что за зверь такой этот GCD и чем он от async/await отличается. Сиди, слушай, а то потом будешь в коде путаться, как мартышка в апельсинах.
GCD (Grand Central Dispatch) — это, сука, низкоуровневый C-API, который тебе самому приходится в потоках и очередях ковыряться, как в дерьме палкой.
async/await — это уже высокоуровневая абстракция Swift Concurrency, где за тебя всё делает компилятор, и ты пишешь почти как синхронный код, только с магическим словечком await.
Таблица, чтобы не ебал мозг:
| Аспект | GCD | async/await |
|---|---|---|
| Уровень абстракции | Низкий, сам копайся в потоках | Высокий, тебе почти нихуя не надо думать |
| Синтаксис | Closures, ад коллбэков, пирамида из пизды | Красивый, последовательный код с await |
| Управление потоками | Сам решай, куда кидать (DispatchQueue.main/global) |
Автоматическое, умная система сама распределяет |
| Отмена задач | DispatchWorkItem.cancel(), и молись, чтобы сработало |
Task.cancel(), проверь Task.isCancelled — всё чётко |
| Обработка ошибок | Через completion handlers, сам придумывай велосипед | Встроенная, через throw/try/catch, как у взрослых |
| Приоритеты | QoS (.userInteractive, .background) | TaskPriority (.high, .medium, .low) |
| Состояние гонки | Забудь синхронизацию — получишь race condition в жопу | Предотвращается через Actors, почти как в сказке |
Вот как это выглядело в старые добрые времена с GCD:
func fetchData(completion: @escaping (Result<Data, Error>) -> Void) {
DispatchQueue.global(qos: .userInitiated).async {
let data = // ... загрузка
DispatchQueue.main.async {
completion(.success(data))
}
}
}
Видишь эту хуйню? Вложенные кложуры, переходы между очередями — один пиздец. Через три таких вызова уже не понять, где ты и куда тебя занесло.
А теперь смотри, как это делают современные ребята с async/await:
func fetchData() async throws -> Data {
// Автоматически выполняется в background pool
let data = try await downloadFromNetwork()
return data
}
// Использование:
Task {
do {
let data = try await fetchData()
await MainActor.run {
updateUI(with: data) // Автоматически на главном потоке
}
} catch {
handleError(error)
}
}
Ну не красота ли, ёпта? Код читается сверху вниз, как книга. Ошибки ловятся там, где надо. И не надо вручную прыгать между очередями — система сама умная.
Основные плюсы async/await, которые тебя с ума сведут:
- Читаемость — линейный код вместо вложенных closures, которые мозг выедают.
- Безопасность — интеграция с Actors, чтобы твои данные не ебнулись от гонок.
- Производительность — cooperative threads вместо создания потоков на каждый чих.
- Интеграция — работа с
@MainActor,TaskGroup,AsyncSequence— всё из коробки.
А когда всё-таки лезть в GCD?
- Когда нужен низкоуровневый контроль над потоками, до последнего винтика.
- Работа с легаси-кодом, который написан ещё при царе Горохе.
- Таймеры (
DispatchSourceTimer), которые надо тонко настраивать. - Барьеры для чтения/записи, если ты всё ещё сам это делаешь.
Короче, async/await — это будущее, блядь. Но и старый добрый GCD пока рано списывать со счетов. Главное — понимать, где что применять, а не тыкать наугад, как слепой крот.