我正在研究GCD机制,我有几个问题。如果你纠正我,如果我搞错了,我会很感激的。
1.问题)据我所知,有4个具有不同优先级的全局并发队列。例如,当我们编写DISPATCH_QUEUE_PRIORITY_HIGH
时,我们会得到其中一个队列。队列不是空的,一些苹果系统进程在它们上运行。因此,当我们在某些队列中添加代码块时,例如,当n是随机整数时,可以是一行中的n个数字任务。
现在,当我们添加代码块时,就像
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
// Heavy calculations
});
在viewDidLoad
中,所有UI
组件都将被阻塞,直到:
我说的对吗?我知道,我们应该在这里使用dispatch_async
,我只是想知道事情是如何工作的。
2.问题)据我所知,所有全局队列都是并发队列,这意味着它可以通过上下文切换或并行处理任务。然而,当我们通过dispatch_sync到达队列时,我们不得不等待,所有的工作都将完成。在这种情况下,唯一不同于串行队列的是操作顺序。例如,如果串行队列有任务1、任务2、任务3和任务4,它将严格按照顺序执行,但并发队列可以更改顺序,以便首先完成轻量级操作。
所以,我的问题是,为什么我们要做dispatch_sync
?据我理解,主线程将被阻塞,直到dispach_sync
代码块完成为止。
发布于 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()
,并将后续代码作为延续步骤(或完成处理程序)放入任务中。但你不能总是这么做。
https://stackoverflow.com/questions/31361489
复制相似问题