← Назад к вопросам

Какие знаешь парадигмы GCD?

2.0 Middle🔥 203 комментариев
#Многопоточность и асинхронность

Комментарии (3)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Парадигмы и шаблоны использования GCD (Grand Central Dispatch)

GCD (Grand Central Dispatch) — это низкоуровневый C-фреймворк для управления параллельными задачами в iOS/macOS, который предоставляет несколько ключевых парадигм и шаблонов проектирования для эффективной работы с многопоточностью. Вот основные из них:

1. Очереди (Queues) — фундаментальная парадигма

GCD использует очередь как абстракцию для выполнения задач. Есть два основных типа:

  • Serial (последовательные) — задачи выполняются строго по очереди, одна за другой.
  • Concurrent (параллельные) — задачи запускаются в порядке добавления, но могут выполняться одновременно.
// Создание собственных очередей
let serialQueue = DispatchQueue(label: "com.example.serial")
let concurrentQueue = DispatchQueue(label: "com.example.concurrent", attributes: .concurrent)

// Использование глобальных системных очередей
DispatchQueue.global(qos: .background).async {
    // Фоновая задача
}

2. Приоритеты и QoS (Quality of Service)

GCD вводит парадигму классов обслуживания, которая заменяет устаревшие приоритеты:

  • .userInteractive — для мгновенных задач UI (анимации, события).
  • .userInitiated — задачи, инициированные пользователем (сохранение документа).
  • .utility — длительные задачи с индикатором прогресса (импорт данных).
  • .background — задачи, невидимые для пользователя (индексация, синхронизация).
DispatchQueue.global(qos: .userInitiated).async {
    let processedData = self.processImage()
    DispatchQueue.main.async {
        self.updateUI(with: processedData) // Возврат в main queue
    }
}

3. Синхронизация доступа к общим ресурсам

Для предотвращения состояний гонки (race conditions) GCD предлагает:

  • Барьеры (dispatch barriers) — для concurrent очередей, обеспечивающие эксклюзивный доступ.
  • Семафоры (dispatch semaphores) — для контроля количества одновременных доступов.
// Пример барьера для thread-safe записи
concurrentQueue.async(flags: .barrier) {
    self.sharedArray.append(newElement) // Эксклюзивный доступ
}

// Пример семафора для ограничения параллельных операций
let semaphore = DispatchSemaphore(value: 3)
for _ in 0..<10 {
    concurrentQueue.async {
        semaphore.wait()
        defer { semaphore.signal() }
        // Критическая секция (макс. 3 потока одновременно)
    }
}

4. Группы задач (Dispatch Groups)

Парадигма для координации набора асинхронных задач:

  • Объединение задач в группу.
  • Ожидание завершения всех задач (wait или notify).
let group = DispatchGroup()
for data in datasets {
    group.enter()
    processDataAsync(data) {
        group.leave()
    }
}
group.notify(queue: .main) {
    print("Все задачи завершены")
}

5. Источники событий (Dispatch Sources)

Мощная парадигма для реакции на системные события:

  • Таймеры (более эффективные, чем Timer).
  • Мониторинг файловой системы.
  • Обработка сигналов UNIX.
let timerSource = DispatchSource.makeTimerSource(queue: .global())
timerSource.setEventHandler { print("Таймер сработал") }
timerSource.schedule(deadline: .now(), repeating: 1.0)
timerSource.activate()

6. Паттерны применения на практике

Однократное выполнение (Dispatch Once)

Хотя в Swift 4+ dispatch_once устарел, его заменяют:

private let initToken: Void = {
    // Инициализация выполняется один раз
}()

Отложенное выполнение (Dispatch After)

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
    self.showTooltip()
}

Очередь операций vs GCD

Важно понимать отличие от OperationQueue: GCD ближе к системе, проще, но OperationQueue предлагает зависимости между задачами, отмену операций и KVO.

Ключевые принципы GCD:

  • Декларативность — описываете что сделать, система решает как.
  • Автоматическое управление пулами потоков — не создавайте потоки вручную.
  • Избегание блокировок (lock-free) — через очереди и барьеры.
  • Приоритет инверсии — система предотвращает блокировку высокоприоритетных задач низкоприоритетными.

Эволюция парадигм: современный Swift переходит к async/await и акторам, которые абстрагируют GCD, но понимание этих основ критично для отладки, оптимизации и работы с legacy-кодом. Например, акторы в Swift используют очереди GCD внутри для изоляции данных.

Какие знаешь парадигмы GCD? | PrepBro