Ответ
Вызов sync (синхронной операции) на concurrent (параллельной) очереди приводит к последовательному выполнению переданной задачи в текущем потоке, при этом параллельное выполнение других задач в этой очереди не блокируется.
Ключевое поведение:
- Блокировка вызывающего потока: Текущий поток блокируется до полного завершения задачи, переданной в
sync. - Задача выполняется НЕ в текущем потоке: Система может выбрать любой поток из пула для выполнения этой задачи, но логика
syncобеспечивает ожидание. - Concurrent-природа очереди сохраняется: Другие задачи, отправленные в эту же очередь через
async, могут выполняться параллельно друг с другом и с задачей внутриsync.
Пример и важное предупреждение:
let concurrentQueue = DispatchQueue(label: "com.example.concurrent", attributes: .concurrent)
print("Начало на главном потоке")
// Эта sync-задача заблокирует главный поток на 2 секунды.
concurrentQueue.sync {
print("Sync Task 1 началась в (Thread.current)")
sleep(2)
print("Sync Task 1 завершилась")
}
// Эта async-задача будет поставлена в очередь и может выполняться параллельно.
concurrentQueue.async {
print("Async Task 2 началась в (Thread.current)")
sleep(1)
print("Async Task 2 завершилась")
}
print("Конец на главном потоке (после sync)")
// Возможный вывод:
// Начало на главном потоке
// Sync Task 1 началась в <NSThread: ...>{number = 1, name = main}
// Sync Task 1 завершилась
// Конец на главном потоке (после sync)
// Async Task 2 началась в <NSThread: ...>{number = 5, name = (null)}
// Async Task 2 завершилась
Главная опасность — взаимная блокировка (deadlock):
concurrentQueue.sync {
// ВНИМАНИЕ: Вызов sync на ТОЙ ЖЕ очереди изнутри себя приводит к deadlock.
concurrentQueue.sync { // Поток заблокирован на внешнем sync и ждет этот внутренний, который никогда не начнется.
print("Этот код никогда не выполнится")
}
}
Вывод: Используйте sync на concurrent очередях с осторожностью, только для простых, быстрых операций синхронизации доступа к общим ресурсам (например, с использованием .sync(flags: .barrier)), и избегайте вложенных вызовов sync на той же очереди.