Может ли deadlock возникнуть в других случаях кроме serial очередей
Что проверяют
Понимаете ли вы deadlock как общий принцип, где участники ждут друг друга, а не как особенность sync на последовательной очереди. Следом обычно спрашивают, как вы найдёте такое зависание в приложении.
Как отвечать
Да, и в iOS таких сценариев несколько:
- барьер на параллельной очереди: внутри блока
syncна собственной concurrent-очереди вызватьqueue.sync(flags: .barrier)на ту же очередь. Барьер ждёт завершения текущего чтения, а чтение ждёт барьер; - семафор на главном потоке:
DispatchSemaphore.wait()в главном потоке, аsignal()должен прийти из колбэка, который доставляется наDispatchQueue.main. Главный поток ждёт сам себя; - блокировки в разном порядке: поток A взял
lockAи ждётlockB, поток B наоборот. Классика, от очередей не зависит; - повторный захват:
NSLockдважды на одном потоке зависает навсегда.NSRecursiveLockэто допускает, аos_unfair_lockв такой ситуации роняет приложение; - исчерпание пула потоков: число рабочих потоков GCD ограничено. Если все заняты блоками, которые ждут семафор, блоку с
signal()поток не достаётся; - Swift Concurrency: кооперативный пул размером примерно с число ядер. Блокирующее ожидание внутри
Task, например семафор, ждущий другую задачу, может остановить весь пул. Внутри асинхронного кода поток не блокируют, а используютawait.
Как искать: поставить приложение на паузу в Xcode и посмотреть стеки всех потоков (bt all в LLDB), ждущие потоки видны сразу. Если завис главный поток при запуске, система убивает приложение по watchdog, и в крэш-репорте будет код 0x8badf00d.
Предотвращение: единый порядок захвата блокировок, отказ от sync и семафоров там, где хватает колбэка или await, и actor вместо ручных очередей.
Где спотыкаются
Отвечают, что на concurrent-очереди deadlock невозможен. Барьер и исчерпание потоков это опровергают.
Используют семафор, чтобы «сделать асинхронный код синхронным», прямо на главном потоке. Работает до первого колбэка на main.
Путают deadlock с тормозами или инверсией приоритетов. Deadlock это вечное ожидание: стеки потоков не меняются от паузы к паузе.