Каковы преимущества и недостатки барьерных задач (Dispatch barrier) в GCD?

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

Ответ

Барьерные задачи (Dispatch barrier) в GCD обеспечивают синхронизацию доступа к общему ресурсу в concurrent очередях.

Преимущества:

  • Синхронизация записи при параллельном чтении: Гарантирует, что задача записи выполнится только после завершения всех ранее поставленных задач, а новые задачи начнут выполняться только после барьерной.
  • Избегание гонок данных: Полезен для операций модификации shared ресурсов (например, массива или словаря).
  • Эффективность: Позволяет сохранить параллельное выполнение задач чтения, блокируя только на время записи.

Недостатки и ограничения:

  • Только для custom concurrent очередей: Не работает с глобальными очередями (DispatchQueue.global()) или serial очередями.
  • Риск взаимоблокировок (deadlock): При неправильном вложенном использовании (например, sync-барьер в той же очереди).
  • Избыточность для простых случаев: Для исключительного доступа к ресурсу проще использовать serial очередь.

Пример использования в Swift:

let concurrentQueue = DispatchQueue(label: "com.example.queue", attributes: .concurrent)
var sharedArray = [String]()

// Параллельные операции чтения
for i in 0..<5 {
    concurrentQueue.async {
        print("Чтение: (sharedArray)")
    }
}

// Барьерная операция записи (выполнится одна, после всех чтений)
concurrentQueue.async(flags: .barrier) {
    sharedArray.append("New Item")
    print("Запись завершена")
}

// Последующие задачи (начнутся только после барьера)
concurrentQueue.async {
    print("После барьера: (sharedArray)")
}