首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >理解dispatch_sync和全局队列

理解dispatch_sync和全局队列
EN

Stack Overflow用户
提问于 2015-07-11 20:25:14
回答 1查看 1.9K关注 0票数 6

我正在研究GCD机制,我有几个问题。如果你纠正我,如果我搞错了,我会很感激的。

1.问题)据我所知,有4个具有不同优先级的全局并发队列。例如,当我们编写DISPATCH_QUEUE_PRIORITY_HIGH时,我们会得到其中一个队列。队列不是空的,一些苹果系统进程在它们上运行。因此,当我们在某些队列中添加代码块时,例如,当n是随机整数时,可以是一行中的n个数字任务。

现在,当我们添加代码块时,就像

代码语言:javascript
运行
复制
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
      // Heavy calculations
});

viewDidLoad中,所有UI组件都将被阻塞,直到:

  1. Apple系统任务将完成(因为我们将任务最后添加到该队列中,并应等到其他系统任务完成)
  2. 直到我们的代码完成。

我说的对吗?我知道,我们应该在这里使用dispatch_async,我只是想知道事情是如何工作的。

2.问题)据我所知,所有全局队列都是并发队列,这意味着它可以通过上下文切换或并行处理任务。然而,当我们通过dispatch_sync到达队列时,我们不得不等待,所有的工作都将完成。在这种情况下,唯一不同于串行队列的是操作顺序。例如,如果串行队列有任务1、任务2、任务3和任务4,它将严格按照顺序执行,但并发队列可以更改顺序,以便首先完成轻量级操作。

所以,我的问题是,为什么我们要做dispatch_sync?据我理解,主线程将被阻塞,直到dispach_sync代码块完成为止。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-07-11 21:13:38

GCD具有4个具有不同优先级的全局并发队列。例如,当我们编写DISPATCH_QUEUE_PRIORITY_HIGH时,我们会得到其中一个队列。队列不是空的,一些苹果系统进程在它们上运行。

在任何给定的时间,队列可能是空的,也可能不是。不可能知道。是的,框架可能会像代码一样向这些队列添加内容。

不过,队列不运行任何东西。队列是一个数据结构。它按部就班地执行任务。GCD管理一组工作线程,根据需要创建新线程或让它们退出。这些工作线程从队列中取出任务并执行它们。

当我们添加代码块时,比如 ( dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0),^{ //重计算}; 在viewDidLoad中,所有UI组件都将被阻塞,直到:1- Apple任务将完成(因为我们在队列中最后添加任务,并且应该等到其他系统任务完成)2-直到我们的代码完成。

顾名思义,dispatch_sync()是同步的。这意味着它在完成要求它做的工作(您传递的块)之前不会返回。是否必须等待队列中的任何其他任务取决于可用的系统资源。正如您所提到的,队列是并发的,因此可以将任务从队列中取出以并发运行。如果有足够的空闲CPU核心,GCD可能启动足够多的工作线程来同时运行队列中的所有任务。因此,您的任务不需要等待其他任务的完成,它只需等待这些任务已经启动(从队列的头上弹出),并等待空闲的工作线程可用。

如果所有系统资源(如CPU核心)都很忙,您只需要等待其他任务的完成。

据我所知,所有全局队列都是并发队列,这意味着它可以通过上下文切换或并行来管理任务。然而,当我们通过dispatch_sync到达队列时,我们不得不等待,所有的工作都将完成。

不,这是错误的,正如我前面所解释的。在dispatch_sync()返回之前,您知道的唯一需要完成的是使用它提交的任务。它不需要等待队列中的任何其他任务,除非所有CPU内核都很忙。

在这种情况下,唯一不同于串行队列的是操作顺序。例如,如果串行队列有任务1、任务2、任务3和任务4,它将严格按照顺序执行,但并发队列可以更改顺序,以便首先完成轻量级操作。

不是的。并发队列严格按照顺序启动操作,就像串行队列一样。只是在当前队列(如果有的话)完成之前,串行队列不会启动另一个操作。全局并发队列将允许其所有操作同时启动和运行,但以可用资源为限。队列无法知道操作是否是轻量级的。

所以,我的问题是,为什么我们要做dispatch_sync?据我理解,主线程将被阻塞,直到dispach_sync代码块完成为止。

并发性和同步行为是两个独立的概念。同步和异步决定了调用方的行为。它确定是否允许调用方在完成工作之前继续工作。

并发任务和串行任务决定提交的任务是如何运行的。并发队列允许任务彼此并发运行。串行队列一次只允许它的一个任务运行。

从主线程调用dispatch_sync()可能是有意义的,但您必须小心。例如,当使用串行队列来同步对由多个线程共享的数据结构的访问时,可能是必要的。一般规则是,您需要避免长时间阻塞主线程。如果你有充分的理由相信它会在很短的时间内被用户察觉的话,你就可以阻止它。

您肯定不想使用主线程中的dispatch_sync()进行“繁重的计算”,正如您所说的那样。

通常,当您需要在继续之前完成任务时,可以使用dispatch_sync()。通常,您可以重构代码以替代使用dispatch_async(),并将后续代码作为延续步骤(或完成处理程序)放入任务中。但你不能总是这么做。

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31361489

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档