首页 文章

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

提问于
浏览
116

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

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 之前执行并完成,对吗?

3 回答

  • 18

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

    这个代码

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

    它可能会在 3 之前打印 2413214312341

    这个代码

    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:dispatch_async一个耗时的任务(任务1)到串行队列

    • 线程2:开始执行任务1

    • 线程1:dispatch_async另一个任务(任务2)到串行队列

    • 线程2:任务1完成 . 开始执行任务2

    • 线程2:任务2完成 .

    你总是看到 12

  • 391

    dispatch_syncdispatch_async 之间的区别很简单 .

    在两个示例中, TASK 1 将始终在 TASK 2 之前执行,因为它在它之前被调度 .

    但是,在 dispatch_sync 示例中,在分派并执行 TASK 1 之后,才会调度 TASK 2 . 这叫做"blocking" . 您的代码等待(或"blocks"),直到任务执行 .

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

  • 3

    它都与主队列有关 . 有4种排列 .

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

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

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

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

    您选择的并发或串行队列取决于您是否需要上一个任务的输出以用于下一个任务 . 如果依赖于上一个任务,则采用串行队列,否则采用并发队列 .

    最后,当我们完成业务时,这是一种渗透回主线程的方式:

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

相关问题