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

Как реализован Барьер?

3.0 Senior🔥 102 комментариев
#Многопоточность и асинхронность

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

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

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

Реализация GCD Barrier в iOS

Барьер (Barrier) в Grand Central Dispatch — это механизм синхронизации, который позволяет контролировать выполнение задач в параллельных очередях. Основная идея: когда задача с барьером попадает в очередь, она выполняется только после завершения всех ранее добавленных задач, и новые задачи не начинаются до завершения этой барьерной задачи.

Принцип работы

// Пример использования барьера в concurrent очереди
let concurrentQueue = DispatchQueue(label: "com.example.concurrent", 
                                    attributes: .concurrent)

// Обычные задачи
concurrentQueue.async {
    print("Задача 1 началась")
    sleep(1)
    print("Задача 1 завершена")
}

concurrentQueue.async {
    print("Задача 2 началась")
    sleep(2)
    print("Задача 2 завершена")
}

// Барьерная задача
concurrentQueue.async(flags: .barrier) {
    print("=== БАРЬЕРНАЯ задача началась ===")
    sleep(1)
    print("=== БАРЬЕРНАЯ задача завершена ===")
}

// Задачи после барьера
concurrentQueue.async {
    print("Задача 3 началась")
    sleep(1)
    print("Задача 3 завершена")
}

Ключевые аспекты реализации

  1. Только для concurrent очередей:

    • Барьеры работают исключительно с concurrent очередями (DispatchQueue с атрибутом .concurrent)
    • В serial очередях они бессмысленны, так как задачи и так выполняются последовательно
  2. Синхронизация доступа к ресурсам:

    class ThreadSafeDictionary<Key: Hashable, Value> {
        private var storage: [Key: Value] = [:]
        private let queue = DispatchQueue(label: "com.example.dictionary", 
                                          attributes: .concurrent)
        
        func set(_ value: Value, forKey key: Key) {
            queue.async(flags: .barrier) {
                self.storage[key] = value
            }
        }
        
        func get(_ key: Key) -> Value? {
            var result: Value?
            queue.sync { // Без барьера - только чтение
                result = self.storage[key]
            }
            return result
        }
    }
    
  3. Реализация в ядре GCD:

    • Барьеры реализованы на уровне планировщика GCD
    • Когда встречается барьерная задача, планировщик:
     - Дожидается завершения всех текущих выполняющихся задач в очереди
     - Выполняет барьерную задачу в **монопольном** режиме
     - После завершения барьера возобновляет обычное параллельное выполнение

Практические сценарии использования

Чтение-запись (Reader-Writer):

class DataManager {
    private var cache: [String: Data] = [:]
    private let queue = DispatchQueue(label: "com.datamanager", 
                                      attributes: .concurrent)
    
    // Множественные одновременные чтения
    func readData(for key: String) -> Data? {
        var data: Data?
        queue.sync {
            data = cache[key]
        }
        return data
    }
    
    // Эксклюзивная запись через барьер
    func writeData(_ data: Data, for key: String) {
        queue.async(flags: .barrier) {
            self.cache[key] = data
        }
    }
}

Барьеры в операциях:

// В OperationQueue через зависимости
let barrierOperation = BlockOperation {
    print("Выполняю синхронизацию")
}

let operations = [op1, op2, op3]
for operation in operations {
    barrierOperation.addDependency(operation)
    operationQueue.addOperation(operation)
}

operationQueue.addOperation(barrierOperation)

Важные ограничения и особенности

  • Глобальные очереди — нельзя использовать барьеры в глобальных очередях (DispatchQueue.global())
  • Асинхронность — барьерные задачи обычно выполняются асинхронно (async), но могут быть и синхронными (sync)
  • Вложенные барьеры — поддерживаются, но требуют осторожности чтобы избежать взаимоблокировок
  • Отмена задач — если барьерная задача отменена, она не выполняется, но барьерный эффект сохраняется

Альтернативы в Swift

Для современных приложений также доступны:

  • Акторы (Actors) в Swift Concurrency
  • NSLock / os_unfair_lock для низкоуровневой синхронизации
  • Semaphores для более сложных сценариев синхронизации

Барьеры в GCD остаются эффективным инструментом для синхронизации доступа к общим ресурсам в concurrent очередях, особенно в legacy-коде или при работе с Objective-C совместимостью.

Как реализован Барьер? | PrepBro