dispatch_async与dispatch_sync区别

转自:https://www.jianshu.com/p/a1ec0db3c710

概述

首先明确几个概念

  • 队列:队列分为串行和并行。串行队列按照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函数返回。

以打电话给查号台为例:

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

示例

异步

 

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"async:1");
    });
NSLog(@"async:2");
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"async:3");
    });
NSLog(@"async:4");

结果为

 

async:2
async:4
async:1
async:3

可以看出,dispatch_async将block追加到线程中后,并未等待,立刻执行后面的代码

同步

 

dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"sync:1");
    });
NSLog(@"sync:2");
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"sync:3");
    });
NSLog(@"sync:4");

结果为

 

sync:1
sync:2
sync:3
sync:4

可以看出,dispatch_sync将block追加到线程中后,等待block执行完毕后才接着执行后面的代码

死锁

 

dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"mainQueue_sync:1");
});

上述代码会造成死锁。原因:main_queue为串行队列,在当前queue上调用sync函数,sync指定的queue也是当前queue。需要执行的block被放到当前queue的队尾等待被执行,因为这是一个串行的queue,调用sync函数会阻塞当前队列,等待block被执行->这个block一直不会被执行->sync函数一直不返回,所以当前queue就被阻塞了,造成了死锁。

说明

开发者要做的只是定义想执行的任务并追加到适当的Dispatch Queue中。

上述引用自苹果官方对GCD的说明,因此Dispatch_async和Dispatch_sync的作用是将block追加到队列中。这句话对于上述理解死锁有很大帮助。

实例

 

print(1)
serialQueue.async {
    print(2)
    serialQueue.sync {
        print(3)
}
print(4)
}
print(5)

分析:只会打印1,2,然后就死锁了。原因是列serialQueue.async的block1被异步追加到串行队列上后,开始执行,这个block1中又被同步追加了一个block2,此时serialQueue被阻塞,等待block2执行完毕,但是block1还未执行完毕,由于是串行队列,block只能按照追加的先后顺序一个一个执行:线程被阻塞->block1停止执行->block2等block1执行完毕->因此就造成了死锁。

参考

  1. GCD有关问题:dispatch_sync(dispatch_get_main_queue(), ^{NSLog(@"Hello ?");}); 死锁的原因
  2. Objective-C高级编程 P161 dispatch_sync



作者:NapoleonY
链接:https://www.jianshu.com/p/a1ec0db3c710
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(IOS)