Ответ
Краткий ответ: Вызывающий поток будет заблокирован до полного завершения синхронной задачи, несмотря на параллельную природу глобальной очереди. Сама задача выполнится в одном из потоков глобальной очереди.
Детали и пример:
Метод DispatchQueue.global().sync выполняет две ключевые операции:
- Отправляет блок кода на выполнение в глобальную параллельную очередь.
- Немедленно блокирует текущий поток, в котором был вызван
.sync, и ждет, пока переданный блок не выполнится полностью.
print("1. До sync на главном потоке")
DispatchQueue.global().sync {
print("2. Внутри sync блока. Выполняется в потоке глобальной очереди: (Thread.current)")
sleep(2) // Имитация долгой работы
print("3. Синхронный блок завершен")
}
print("4. После sync. Главный поток разблокирован.")
Вывод будет строго последовательным:
1. До sync на главном потоке
2. Внутри sync блока. Выполняется в потоке глобальной очереди: <NSThread: 0x...>{number = 4, name = (null)}
3. Синхронный блок завершен
4. После sync. Главный поток разблокирован.
Важные предупреждения и best practices:
- Дедлок на главном потоке: Вызов
DispatchQueue.main.syncиз главного потока приведет к гарантированному дедлоку, так как поток пытается заблокировать сам себя. - Цель использования
.sync:- Для обеспечения thread-safety при доступе к общему ресурсу.
- Когда необходимо получить результат выполнения задачи прежде, чем продолжить работу в текущем потоке.
-
Альтернатива: Вместо
global().syncдля простой синхронизации часто используют serial очередь.let threadSafeQueue = DispatchQueue(label: "com.threadsafe.queue") var sharedValue = 0 threadSafeQueue.sync { // Безопасное чтение/запись sharedValue sharedValue += 1 } - Отличие от
.async: Метод.asyncнемедленно возвращает управление вызывающему потоку, не дожидаясь выполнения блока.