ios 关于GCD 浅谈
- 笔者也是在边学习边整理,有不对的地方欢迎指出
- 类型:
- (1)并发队列(Concurrent Dispatch Queue)
- 可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务)并发功能只有在异步(dispatch_async)函数下才有效
- (2)串行队列(Serial Dispatch Queue)
- 让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)
- 将任务添加到队列中,GCD会自动将队列中的任务取出,放到对应的线程中执行,任务的取出遵循队列的FIFO原则:先进先出,后进后出
- 同步和异步决定了要不要开启新的线程
- 同步:在当前线程中执行任务,不具备开启新线程的能力
- 异步:在新的线程中执行任务,具备开启新线程的能力
- 并发和串行决定了任务的执行方式
- 并发:多个任务并发(同时)执行
- 串行:一个任务执行完毕后,再执行下一个任务
- (1)用异步函数往并发队列中添加任务
- 总结:同时开启多个子线程
- (2)用异步函数往串行队列中添加任务
- 总结:会开启线程,但是只开启一个线程
- (3)用同步函数往并发队列中添加任务
- 总结:不会开启新的线程,并发队列失去了并发的功能
- (4)用同步函数往串行队列中添加任务
- 总结:不会开启新的线程
- 说明:同步函数不具备开启线程的能力,无论是什么队列都不会开启线程;异步函数具备开启线程的能力,开启几条线程由队列决定(串行队列只会开启一条新的线程,并发队列会开启多条线程)。
- 同步函数
- (1)并发队列:不会开线程
- (2)串行队列:不会开线程
- 异步函数
- (1)并发队列:能开启N条线程
- (2)串行队列:开启1条线程
- dispatch_async(queue,block) async 异步队列,dispatch_async 函数会立即返回, block会在后台异步执行。
- dispatch_sync(queue,block) sync 同步队列,dispatch_sync 函数不会立即返回,及阻塞当前线程,等待 block同步执行完成。
- 下面上代码,可以理解的更透彻一些:
- (1)同步串行队列
- 这里加sleep方便从运行结果更好的看出区别
- 如图-同步串行队列
- 可以看出,这里的时间间隔就是sleep,也就是说会按顺序添加到队列中,并且只能等上一个任务结束才能进行下一个任务,所有的操作都是在主线程中进行,并不会开辟新的子线程。
- 如图-同步串行队列-2
- (2)同步并发队列
- 从运行结果显而易见,同步串行和同步并发结果是相同的,也是上一个任务结束才能进行下一个任务,也是在主线程中进行,并且也没有开辟新的子线程,也就是说同步函数不具备开启线程的能力。
- 如图-同步并发队列、同步并发队列-2
- (3)异步串行队列
- 从结果可以看出,同步和异步串行队列的区别主要在于开辟子线程的能力,在同步串行队列中,所有的任务都是在主线程执行,在异步串行队列中,会开辟一个新的子线程,不论有多少个任务,都只会开辟一个子线程。
- 如图-异步串行队列、异步串行队列-2
- (4)异步并发队列
- 从结果可以看出,异步并发队列是多个任务同时执行,并且会根据任务的多少开辟多个子线程,可以把sleep去掉会发现,输出的顺序是无序的。
- 如图-异步并发队列、异步并发队列-2
- (5)GCD延时操作
- 如图-GCD延时操作
- (6)队列组
- 首先创建队列组,把需要执行的任务都放到队列组里,notify是监听队列组中所有任务完成之后才会调用的。
- 如图-队列组、队列组-2
- 死锁问题(笔者也是根据自己的理解,有问题之处还望指出)
- 其实死锁的原因就是线程之间相互阻塞(相互等待)
- 第一种情况:
- 因为同步函数会等block块执行完成之后才接着往下执行,执行到图中所示位置时,会在主线程新加入一个队列,所以sync会等待block执行完成之后在继续往下执行,但是sync在主线程中,而且是串行队列,sync是后加入进来的,sync想执行必须等主线程执行完成,主线程等待sync返回,所以执行到此处就会造成死锁,不会继续往下执行了。简单来说,就是sync等待主线程执行完成, 主线程等待sync函数返回。
- 如图-死锁1、死锁2
- 第二种情况:
- 对比下面图的运行结果,可以看出,异步函数中不会等待block执行完成,会立刻返回,两个同步函数之间相互等待,造成死锁。
- 从输出时间可以看出,1和2几乎同时执行,因为是在异步函数中,当执行到2的sync时1存在两种情况:(1)执行中 (2)已经执行完成 ,而且主线程中并没有执行耗时操作,所以1和2同时完成;如果把2处改成sleep(3),那么就会出现前面说异步函数时出现的情况,输出时间至少会差3秒;如果阻塞了主线程,2处的sync就会一直等待永远都不会执行。
- 如图-死锁3、死锁4
- 最后附上小demo。
- GCD.zip