串行队列上的分派异步和分派同步之间的区别?

我创建了一个这样的串行队列:

    dispatch_queue_t _serialQueue = dispatch_queue_create("com.example.name", DISPATCH_QUEUE_SERIAL);

dispatch_async这样叫有什么区别

 dispatch_async(_serialQueue, ^{ /* TASK 1 */ });
dispatch_async(_serialQueue, ^{ /* TASK 2 */ });

dispatch_sync在这个串行队列中是这样调用的吗?

 dispatch_sync(_serialQueue, ^{ /* TASK 1 */ });
dispatch_sync(_serialQueue, ^{ /* TASK 2 */ });

我的理解是,无论使用哪种分派方法,TASK 1都将在 TASK 2之前执行并完成,对吗?

45860 次浏览

是的。使用串行队列确保任务的串行执行。唯一的区别是,dispatch_sync只在块完成后返回,而 dispatch_async在添加到队列后返回,可能不会完成。

这个密码

dispatch_async(_serialQueue, ^{ printf("1"); });
printf("2");
dispatch_async(_serialQueue, ^{ printf("3"); });
printf("4");

它可以打印 241321431234,但 1总是在 3之前

这个密码

dispatch_sync(_serialQueue, ^{ printf("1"); });
printf("2");
dispatch_sync(_serialQueue, ^{ printf("3"); });
printf("4");

它总是打印 1234


注: 对于第一个代码,它 不会打印 1324。因为 printf("3")被发送 之后 printf("2")被执行。并且一个任务只能被执行 之后它被分派。


任务的执行时间不会改变任何东西。这段代码总是打印 12

dispatch_async(_serialQueue, ^{ sleep(1000);printf("1"); });
dispatch_async(_serialQueue, ^{ printf("2"); });

可能发生的是

  • 线程1: 向串行队列发送一个耗时的任务(任务1)
  • 线程2: 开始执行任务1
  • 线程1: 向串行队列发送另一个任务(任务2)
  • 线程2: 任务1完成。开始执行任务2
  • 线程2: 任务2完成。

你总能看到 12

dispatch_syncdispatch_async的区别很简单。

在您的两个示例中,TASK 1总是在 TASK 2之前执行,因为它在 TASK 2之前被调度。

然而,在 dispatch_sync示例中,直到 TASK 1被发送到 然后被处决之后,才会发送 TASK 2。这叫做 “阻挡”。代码等待(或“块”)直到任务执行。

dispatch_async示例中,代码不会等待执行完成。这两个块都将分派(并进入队列)到队列,其余代码将继续在该线程上执行。然后在将来的某个时刻(取决于向队列分派了什么) ,Task 1将执行,然后 Task 2将执行。

它们都与主队列有关,共有4种排列方式。

I)串行队列,异步分派: 这里的任务将一个接一个地执行,但主线程(对 UI 的影响)不会等待返回

串行队列,分派同步: 这里的任务将一个接一个地执行,但主线程(对 UI 的影响)将显示延迟

并发队列,异步调度: 这里的任务将并行执行,主线程(对 UI 的影响)将不会等待返回,将是平稳的。

并发队列,分派同步: 这里任务将并行执行,但主线程(对 UI 的影响)将显示延迟

并发队列或串行队列的选择取决于是否需要前一个任务的输出来完成下一个任务。如果依赖于前面的任务,则采用串行队列,否则采用并发队列。

最后,当我们完成我们的工作时,这是一种回归主线的方法:

DispatchQueue.main.async {
// Do something here
}