GCD全局队列中的任务在主线程上运行。

3
下面的代码:
DispatchQueue.main.async {
    print(Thread.current)
    DispatchQueue.global().sync {
        print(Thread.current)
    }
}

打印

<_NSMainThread: 0x60000059c140>{number = 1, name = main}
<_NSMainThread: 0x60000059c140>{number = 1, name = main}

从技术上讲,全局队列会找到一个空闲线程来运行任务,这可能是主线程。

是否有明确的规则表明将任务添加到全局队列时将在主线程上执行?

因此,将耗时的任务放入全局队列不会影响主线程。

2个回答

2

您说:

从技术上讲,全局队列会找到一个空闲的线程来运行任务,这可能是主线程。

通常情况下,全局队列会从工作线程池中选择适当服务质量的线程。在获取工作线程时,并不是随机获取主线程。它只从其工作线程池中选择。

您在这里看到的是针对同步调用(但不是异步调用)的一个非常特定的优化。正如 sync文档所述

为了提高性能,[sync] 尽可能在当前线程上执行块,...

由于在同步调度期间当前线程将被阻塞,因此可以避免不需要或不希望的昂贵上下文切换。这是一个巧妙的小优化。

那么,什么情况下不会使用上述性能优化呢?上面的文档引用继续说:

...唯一的例外是,提交到主分派队列的块始终在主线程上运行。

因此,如果您反过来执行您的示例(即从后台队列同步调度到主队列,或任何使用主队列作为其最终“目标”的队列),则优化将被关闭,并且它将执行到主线程的上下文切换,无论如何。必须这样做,因为某些 API 调用等必须在主线程上执行,因此在这种情况下禁用了优化。

还有其他不太好记录的情况,可能不会使用此优化。建议不要过度依赖此优化。只需确保当 GCD 可以时,它将尝试避免同步调度任务的昂贵上下文切换。


0

同步任务将会阻塞您的调用线程,也就是代码中的主线程。

即使全局队列中的任务被分派到了全局线程而不是主线程,主线程仍然需要等待任务完成。

在这种情况下,GCD 会自动优化同步分派,以便让任务在调用线程上执行,而不是让调用线程等待。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接