GCD全局队列任务在主线程执行的判定规则是什么?
你给出的示例代码恰好命中了GCD的同步提交优化规则:外层DispatchQueue.main.async的闭包已经运行在主线程,此时调用DispatchQueue.global().sync提交任务,GCD直接在当前主线程执行了全局队列的任务,因此两次打印都输出主线程。
触发全局队列任务在主线程执行的明确规则
该现象不是全局队列随机调度到空闲主线程,而是GCD固定的sync线程跳跃优化策略,仅当同时满足以下所有条件时才会触发:
- 提交任务的调用方当前运行在主线程
- 使用
sync同步方法提交任务到全局并发队列 - 目标全局队列的QoS等级不低于当前主线程的QoS等级
优化的核心逻辑是:同步提交会阻塞调用线程等待任务执行完成,全局并发队列本身没有绑定专属线程,因此直接在当前空闲的调用线程执行任务,可以避免不必要的线程切换开销,提升执行效率。
绝对不会触发主线程执行的场景
- 所有通过
async异步提交到全局队列的任务,永远不会调度到主线程运行,只会使用后台线程 - 从非主线程的其他线程提交到全局队列的任务,不会主动调度到主线程执行
避免耗时任务阻塞主线程的方案
- 耗时任务一律使用
async异步提交到全局队列,不要使用sync同步提交,从根源上规避优化触发 - 若业务逻辑必须使用同步提交,可以自行创建专属的串行/并发队列,专属队列的同步提交不会触发跳主线程的优化
- 可将耗时任务提交到QoS等级为
.background的全局队列,其优先级低于主线程默认QoS,不会触发主线程执行的优化
内容的提问来源于stack exchange,提问作者anb
相关产品推荐
相关产品推荐

