为什么DispatchGroup搭配主队列会死锁,使用全局队列却正常?
问题1:为什么主队列不搭配DispatchGroup时可以正常运行,和DispatchGroup结合使用时就会出现死锁?
首先明确两个核心规则:
- 主队列是串行队列,所有提交到主队列的任务,必须按顺序排队,等待当前正在主线程执行的任务结束后,才能被调度到主线程运行
group.wait()的作用是阻塞当前线程,直到分组内所有未完成的任务都调用group.leave()才会解除阻塞
Code1没有死锁的原因:你没有调用wait()阻塞主线程,主线程提交完DispatchQueue.main.asyncAfter延迟任务后直接往下执行// stuff,后续主线程空闲时再执行延迟任务,整个流程没有阻塞,自然不会死锁,只是不符合你要等待延迟任务结束再跑// stuff的需求。
Code2死锁是典型的循环等待:
你所有代码都运行在主线程中,当执行到group.wait()时,主线程直接被阻塞,停在这一行等待group.leave()调用。但你提交的延迟任务是派到主队列的,主队列的排队规则要求必须等当前正在主线程运行的任务(就是包含wait()的这段代码)执行完,才能调度这个延迟任务。此时主线程被wait()卡着永远走不完,延迟任务永远拿不到主线程的执行权限,永远不会调用group.leave(),就形成了死锁。
问题2:为什么使用DispatchGroup实现代码延时执行时,必须搭配全局队列才能正常运行?
全局队列是并行队列,提交到全局队列的任务会被系统调度到后台子线程执行,不需要占用主线程的执行资源。
你把延迟任务提交到全局队列后,即使主线程被group.wait()阻塞,全局队列的调度不受任何影响:1秒延迟结束后,系统会分配后台子线程执行延迟任务的闭包,调用group.leave()。leave()触发后,wait()的阻塞条件解除,主线程恢复运行,继续执行后续的// stuff代码,完全符合预期。
内容的提问来源于stack exchange,提问作者geohei
相关产品推荐
相关产品推荐

