dispatch_async与dispatch_sync区别

283 阅读2分钟

首先明确几个概念

  • 队列:队列分为串行和并行。串行队列按照A、B、C、D的顺序添加四个任务,这四个任务按照顺序执行,结束顺序也肯定是A、B、C、D,而并行队列同时执行这四个任务,完成的顺序因此也是随机的。
  • 异步执行(async)和同步执行(sync):使用dispatch_async调用一个block,这个block会被放到指定的queue_1队列尾等待执行,至于这个block是被并行还是串行执行,只和dispatch_async中的指定的queue_1有关,但是dispatch_async会马上返回。使用dispatch_sync同样也是把block放到指定的queue_2上执行,但是会等待这个block执行完毕后才返回,这期间会阻塞当前运行调用dispatch_async或dispatch_sync代码的queue(通常为main_queue)直到sync函数返回。

以打电话给查号台为例:

  • 同步:打电话给查号台,问某个地方的电话号码,接线员会告诉你稍等,然后为你查号,此时你的电话没有挂断,其他的电话也不能打进来,等到接线员查找到了你要找的电话号,告诉你后,才将电话挂断
  • 异步:打电话给查号台,问某个地方的电话号码,接线员知道了你的请求后,会立刻挂断电话,此时其他的电话可以打进来。然后开始为你查号。等到查找到了你要找的电话号,会再打电话通知你。

死锁问题:

// 前提条件:当前的 queue 为 main_queue
dispatch_sync(dispatch_get_main_queue(), ^{
     NSLog(@"mainQueue_sync:1");
});

上述代码会造成死锁。

原因:main_queue 为串行队列,dispath_sync为同步执行,这句代码的意思可以理解为以同步执行的方式在主线程中执行block,但是因为是sync所以当调用到这句代码时会阻塞线程以等待执行完毕,但是block需要在主线程中执行,而主线程已经被阻塞,所以造成死锁。、

引用苹果官方对GCD的说明:dispatch_async和dispatch_sync的作用是将block中的内容追加到队列中执行,这样理解死锁可能会更加清楚

一般串行队列中 sync 到自身上会产生死锁,sync 到其他队列上一般不会产生死锁,如在自定义 queue 中 sync main_queue,等到 main_queue 执行完毕再继续执行操作。

主线程应该用于处理UI更新和用户交互,任何可能阻塞主线程的行为都应该被避免。