Ответ
Барьерная задача (Dispatch Barrier) — это специальный тип задачи в Grand Central Dispatch (GCD), которая при добавлении в concurrent очередь заставляет очередь выполнить её эксклюзивно относительно всех других задач в этой же очереди.
Принцип работы:
- Все задачи, добавленные в очередь до барьерной, выполняются как обычно (параллельно, если очередь concurrent).
- Когда наступает очередь барьерной задачи, очередь приостанавливается и выполняет только её, пока та не завершится.
- После завершения барьерной задачи очередь возобновляет параллельное выполнение задач, добавленных после неё.
Типичный use-case: Реализация потокобезопасного кэша или структуры данных с паттерном "множество читателей, один писатель" (Multiple Readers, Single Writer).
Пример: Потокобезопасный кэш с использованием барьера
class ThreadSafeCache<Key: Hashable, Value> {
private let concurrentQueue = DispatchQueue(
label: "com.example.cacheQueue",
attributes: .concurrent // 1. Очередь ДОЛЖНА быть concurrent
)
private var storage: [Key: Value] = [:]
// ЧТЕНИЕ: может выполняться параллельно многими потоками
func getValue(for key: Key) -> Value? {
concurrentQueue.sync {
storage[key]
}
}
// ЗАПИСЬ: выполняется эксклюзивно благодаря барьеру
func setValue(_ value: Value, for key: Key) {
concurrentQueue.async(flags: .barrier) { // 2. Флаг .barrier
storage[key] = value
}
}
}
Важные ограничения:
- Барьер работает только с concurrent очередями, созданными вручную (с атрибутом
.concurrent). - Не работает с глобальными очередями (
DispatchQueue.global()), главной очередью (DispatchQueue.main) или последовательными (serial) очередями. - В Swift Concurrency аналогичная семантика достигается с помощью акторов (
actor), которые обеспечивают эксклюзивный доступ к своим данным.