我创建了一个这样的串行队列:
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
之前执行并完成,是吗?
答案 0 :(得分:393)
是。使用串行队列可确保任务的串行执行。唯一的区别是dispatch_sync
仅在块完成后返回,而dispatch_async
在添加到队列后返回并且可能没有完成。
代码
dispatch_async(_serialQueue, ^{ printf("1"); });
printf("2");
dispatch_async(_serialQueue, ^{ printf("3"); });
printf("4");
它可能会在2413
之前打印2143
或1234
或1
但3
代码
dispatch_sync(_serialQueue, ^{ printf("1"); });
printf("2");
dispatch_sync(_serialQueue, ^{ printf("3"); });
printf("4");
始终打印1234
注意:对于第一个代码,不会打印1324
。因为 printf("3")
执行后会调度 {em}。 分派后,只能执行任务。
任务的执行时间不会改变任何事情。此代码始终打印printf("2")
12
可能发生的事情是
你总是看到dispatch_async(_serialQueue, ^{ sleep(1000);printf("1"); });
dispatch_async(_serialQueue, ^{ printf("2"); });
答案 1 :(得分:18)
dispatch_sync
和dispatch_async
之间的区别很简单。
在您的两个示例中,TASK 1
将始终在TASK 2
之前执行,因为它已在之前发送。
但是,在dispatch_sync
示例中,在{em>分发并执行之后,您才会发送TASK 2
。这称为"blocking"。您的代码等待(或“阻止”),直到任务执行。
在TASK 1
示例中,您的代码不会等待执行完成。两个块都将分派(并入队)到队列中,其余代码将继续在该线程上执行。然后在将来的某个时刻,(取决于已分配到队列中的其他内容),dispatch_async
将执行,然后Task 1
将执行。
答案 2 :(得分:3)
所有与主队列有关。有4个排列。
i)串行队列,分派异步:这里任务将一个接一个地执行,但是主线程(对UI起作用)不会等待返回
ii)串行队列,调度同步:这里的任务将一个接一个地执行,但主线程(UI上的效果)将显示延迟
iii)并发队列,分派异步:在这里任务将并行执行,并且主线程(UI上的效果)将不等待返回,并且将保持平稳。
iv)并发队列,调度同步:这里任务将并行执行,但是主线程(UI上的效果)将显示滞后
您对并发队列或串行队列的选择取决于您是否需要下一个任务的上一个任务的输出。如果您依赖于上一个任务,则采用串行队列,否则采用并发队列。
最后,当我们完成业务时,这是一种渗透回主线程的方法:
DispatchQueue.main.async {
// Do something here
}