ios 串行队列上的 dispatch_async 和 dispatch_sync 之间的区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19822700/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 02:47:51  来源:igfitidea点击:

Difference between dispatch_async and dispatch_sync on serial queue?

iosmultithreadinggrand-central-dispatch

提问by JRG-Developer

I've created a serial queue like this:

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

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

What's the difference between dispatch_asynccalled like this

什么之间的差异dispatch_async被称为像这样

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

And dispatch_synccalled like this on this serial queue?

dispatch_sync在这个串行队列上这样调用?

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

My understanding is that, regardless of which dispatch method is used, TASK 1will be executed and completed before TASK 2, correct?

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

回答by Bryan Chen

Yes. Using serial queue ensure the serial execution of tasks. The only difference is that dispatch_synconly return after the block is finished whereas dispatch_asyncreturn after it is added to the queue and may not finished.

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

for this code

对于此代码

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

It may print 2413or 2143or 1234but 1always before 3

它可能会打印2413214312341总是在此之前3

for this code

对于此代码

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

it always print 1234

它总是打印 1234



Note: For first code, it won'tprint 1324. Because printf("3")is dispatched afterprintf("2")is executed. And a task can only be executed afterit is dispatched.

注意:对于第一个代码,它不会打印1324. 因为printf("3")printf("2")执行分派的。并且任务只有在分派才能执行。



The execution time of the tasks doesn't change anything. This code always print 12

任务的执行时间不会改变任何东西。此代码始终打印12

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

What may happened is

可能发生的事情是

  • Thread 1: dispatch_async a time consuming task (task 1) to serial queue
  • Thread 2: start executing task 1
  • Thread 1: dispatch_async another task (task 2) to serial queue
  • Thread 2: task 1 finished. start executing task 2
  • Thread 2: task 2 finished.
  • 线程 1:dispatch_async 一个耗时的任务(任务 1)到串行队列
  • 线程2:开始执行任务1
  • 线程 1:dispatch_async 另一个任务(任务 2)到串行队列
  • 线程 2:任务 1 完成。开始执行任务2
  • 线程 2:任务 2 完成。

and you always see 12

你总是看到 12

回答by Dave DeLong

The difference between dispatch_syncand dispatch_asyncis simple.

dispatch_sync和之间的区别dispatch_async很简单。

In both of your examples, TASK 1will always execute before TASK 2because it was dispatched before it.

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

In the dispatch_syncexample, however, you won't dispatch TASK 2until after TASK 1has been dispatched and executed. This is called "blocking". Your code waits (or "blocks") until the task executes.

dispatch_sync但是,在该示例中,您将TASK 2TASK 1已分派并执行之后才进行分派。这称为“阻塞”。您的代码等待(或“阻塞”)直到任务执行。

In the dispatch_asyncexample, your code will not wait for execution to complete. Both blocks will dispatch (and be enqueued) to the queue and the rest of your code will continue executing on that thread. Then at some point in the future, (depending on what else has been dispatched to your queue), Task 1will execute and then Task 2will execute.

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

回答by rd_

It is all related to main queue. There are 4 permutations.

这一切都与主队列有关。有4种排列。

i) Serial queue, dispatch async : Here the tasks will execute one after the other, but the main thread(effect on UI) will not wait for return

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

ii) Serial queue, dispatch sync: Here the tasks will execute one after the other, but the main thread(effect on UI) will show lag

ii) 串行队列,调度同步:这里的任务会一个接一个执行,但主线程(对UI的影响)会出现滞后

iii) Concurrent queue, dispatch async : Here the tasks will execute in parallel and the main thread(effect on UI ) will not wait for return and will be smooth.

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

iv) Concurrent queue, dispatch sync : Here the tasks will execute in parallel, but the main thread(effect on UI) will show lag

iv) 并发队列,调度同步:这里的任务将并行执行,但主线程(对 UI 的影响)会出现滞后

Your choice of concurrent or serial queue depends on if you need an output from a previous task for the next one. If you depend on the previous task, adopt the serial queue else take concurrent queue.

您选择并发队列还是串行队列取决于您是否需要为下一个任务提供前一个任务的输出。如果依赖上一个任务,则采用串行队列,否则采用并发队列。

And lastly this is a way of penetrating back to the main thread when we are done with our business :

最后,这是一种在我们完成业务后返回到主线程的方法:

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