DispatchQueue.global().sync与主线程的区别及两段同输出代码差异分析
关于DispatchQueue.global().sync的几个问题解答
一、DispatchQueue.global().sync 与主线程的区别
- 队列类型与职责不同:主线程归属主队列(
DispatchQueue.main),是串行队列,专门负责UI渲染、用户交互等操作;global()是系统提供的并发队列(默认优先级),用于处理非UI类的后台任务,比如耗时计算、文件IO等。 - 执行线程不同:主线程的代码始终在APP的主线程上运行;
global().sync的闭包代码会在全局并发队列管理的某条后台线程执行(但调用线程会等待它完成)。 - 使用限制不同:主线程不能执行耗时操作,否则会导致UI卡顿、APP无响应;
global()队列适合承载耗时任务,sync调用会阻塞当前线程,需避免在主线程用它执行耗时逻辑。
二、两段输出相同代码的差异
两段代码输出顺序都是1→k→2→3→4,但底层执行逻辑有本质区别:
- 第一段代码:所有
print语句在当前线程(若在主线程调用则全程在主线程)连续串行执行,没有任何线程切换,是最基础的同步执行逻辑。 - 第二段代码:
print("1")在当前线程执行;- 调用
global().sync时,当前线程立即阻塞暂停,闭包print("k")被分配到全局并发队列的某条后台线程执行; - 闭包执行完成后,当前线程才被唤醒,继续执行后续的
print("2")到print("4")。
简言之:第一段是单线程串行执行,第二段是「当前线程阻塞等待+后台线程执行闭包」的组合,最终因sync的等待特性,输出顺序保持一致。
三、sync在global()队列中的工作原理
sync(同步)在全局并发队列中的执行流程可拆解为以下步骤:
- 提交任务:将闭包任务提交至
global()并发队列。 - 阻塞调用线程:发起
sync调用的线程会立刻进入等待状态,暂停执行后续代码。 - 调度执行任务:全局并发队列从自身线程池取出空闲线程(或根据系统调度创建新线程),执行提交的闭包任务。
- 唤醒调用线程:闭包任务执行完毕后,全局队列通知被阻塞的调用线程,调用线程恢复执行后续代码。
- 风险提示:如果调用
global().sync的线程本身就是全局并发队列的线程,可能触发死锁——当前线程在等待自己执行的任务完成,陷入循环等待。
内容的提问来源于stack exchange,提问作者neeraj joshi
相关产品推荐
相关产品推荐

