В чем разница между очередью Async и Concurrent?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Разница между Async и Concurrent очередями в GCD
Async vs Sync
Async и Sync — это не очереди, а способы добавления задач в очередь.
Async (асинхронный):
DispatchQueue.global().async {
// Код выполнится позже
// Функция вернёт управление сразу
print("Async: выполнится в фоне")
}
print("После async")
// Вывод: После async → Async: выполнится в фоне
Sync (синхронный):
DispatchQueue.global().sync {
// Код выполнится сейчас
// Функция ждёт завершения
print("Sync: выполнится сейчас")
}
print("После sync")
// Вывод: Sync: выполнится сейчас → После sync
Serial Queue (последовательная очередь)
Serial Queue — выполняет задачи одну за другой:
let serialQueue = DispatchQueue(label: "com.example.serial")
serialQueue.async { print("Task 1") } // Выполнится 1-й
serialQueue.async { print("Task 2") } // Выполнится 2-й
serialQueue.async { print("Task 3") } // Выполнится 3-й
// Вывод: Task 1 → Task 2 → Task 3
Гарантирует порядок!
Concurrent Queue (параллельная очередь)
Concurrent Queue — выполняет задачи одновременно:
let concurrentQueue = DispatchQueue(
label: "com.example.concurrent",
attributes: .concurrent
)
concurrentQueue.async { print("Task 1") } // Может выполниться в любом порядке
concurrentQueue.async { print("Task 2") }
concurrentQueue.async { print("Task 3") }
// Вывод: Task 1 → Task 3 → Task 2 (случайный порядок)
Не гарантирует порядок!
Сравнительная таблица
| Serial | Concurrent | |
|---|---|---|
| Порядок | Гарантирован | Не гарантирован |
| Параллелизм | Нет (одна задача) | Да (несколько задач) |
| Потоки | 1 поток | Несколько потоков |
| Производительность | Медленнее | Быстрее |
| Синхронизация | Встроена | Нужна вручную |
Global Queue (встроенная concurrent)
DispatchQueue.global().async { // Встроенная concurrent queue
// Может выполняться параллельно с другим кодом
}
Практический пример
Serial Queue для синхронизации:
class DataManager {
private let dataQueue = DispatchQueue(label: "com.example.data")
private var data: [String] = []
func addData(_ item: String) {
dataQueue.async { // Serial = безопасно
self.data.append(item)
}
}
func getData() -> [String] {
var result: [String] = []
dataQueue.sync { // Ждём завершения
result = self.data
}
return result
}
}
Concurrent Queue для параллельных операций:
let concurrentQueue = DispatchQueue(
label: "com.example.processing",
attributes: .concurrent
)
for item in items {
concurrentQueue.async { // Все параллельно
process(item)
}
}
Когда использовать
Serial Queue: ✅ Синхронизация доступа к ресурсам ✅ Когда нужен гарантированный порядок ✅ Database access ✅ Singleton управление
Concurrent Queue: ✅ Параллельная обработка ✅ Когда порядок не важен ✅ Bulk операции ✅ Network запросы
Барьер в Concurrent Queue
let concurrentQueue = DispatchQueue(
label: "com.example.concurrent",
attributes: .concurrent
)
concurrentQueue.async { print("Read 1") }
concurrentQueue.async { print("Read 2") }
// Барьер: ждёт завершения всех, затем выполняет
concurrentQueue.async(flags: .barrier) {
print("Write (exclusive)") // Одна задача
}
concurrentQueue.async { print("Read 3") }
Ключевые правила
✅ Async — добавить задачу, вернуть управление ✅ Sync — ждать завершения задачи ✅ Serial — одна задача, гарантированный порядок ✅ Concurrent — несколько задач одновременно ❌ Никогда sync в главный поток из главного потока ❌ Не используй sync для долгих операций
Правильный выбор queue типа критичен для производительности и безопасности потоков.