注册

ios 关于GCD 浅谈

  • 笔者也是在边学习边整理,有不对的地方欢迎指出
​         

图片1.png

  •  类型:
  • (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方便从运行结果更好的看出区别
  • 如图-同步串行队列

  • 同步串行队列.png

  • 可以看出,这里的时间间隔就是sleep,也就是说会按顺序添加到队列中,并且只能等上一个任务结束才能进行下一个任务,所有的操作都是在主线程中进行,并不会开辟新的子线程。
  • 如图-同步串行队列-2
         

同步串行队列-2.png

  • (2)同步并发队列
  • 从运行结果显而易见,同步串行和同步并发结果是相同的,也是上一个任务结束才能进行下一个任务,也是在主线程中进行,并且也没有开辟新的子线程,也就是说同步函数不具备开启线程的能力。
  • 如图-同步并发队列、同步并发队列-2
       

同步并发队列.png

       

同步并发队列-2.png

  • (3)异步串行队列
  • 从结果可以看出,同步和异步串行队列的区别主要在于开辟子线程的能力,在同步串行队列中,所有的任务都是在主线程执行,在异步串行队列中,会开辟一个新的子线程,不论有多少个任务,都只会开辟一个子线程。
  • 如图-异步串行队列、异步串行队列-2
       

异步串行队列.png

       

异步串行队列-2.png

  • (4)异步并发队列
  • 从结果可以看出,异步并发队列是多个任务同时执行,并且会根据任务的多少开辟多个子线程,可以把sleep去掉会发现,输出的顺序是无序的。
  • 如图-异步并发队列、异步并发队列-2
       

异步并发队列.png

       

同步并发队列-2.png

  • (5)GCD延时操作
  • 如图-GCD延时操作
       

GCD延时操作.png

  • (6)队列组
  • 首先创建队列组,把需要执行的任务都放到队列组里,notify是监听队列组中所有任务完成之后才会调用的。
  • 如图-队列组、队列组-2
       

队列组.png

       

队列组-2.png

  • 死锁问题(笔者也是根据自己的理解,有问题之处还望指出)
  • 其实死锁的原因就是线程之间相互阻塞(相互等待)
  •  
  • 第一种情况:
  • 因为同步函数会等block块执行完成之后才接着往下执行,执行到图中所示位置时,会在主线程新加入一个队列,所以sync会等待block执行完成之后在继续往下执行,但是sync在主线程中,而且是串行队列,sync是后加入进来的,sync想执行必须等主线程执行完成,主线程等待sync返回,所以执行到此处就会造成死锁,不会继续往下执行了。简单来说,就是sync等待主线程执行完成, 主线程等待sync函数返回。
  • 如图-死锁1、死锁2
       

死锁1.png

       

死锁2.png

  • 第二种情况:
  • 对比下面图的运行结果,可以看出,异步函数中不会等待block执行完成,会立刻返回,两个同步函数之间相互等待,造成死锁。
  • 从输出时间可以看出,1和2几乎同时执行,因为是在异步函数中,当执行到2的sync时1存在两种情况:(1)执行中 (2)已经执行完成 ,而且主线程中并没有执行耗时操作,所以1和2同时完成;如果把2处改成sleep(3),那么就会出现前面说异步函数时出现的情况,输出时间至少会差3秒;如果阻塞了主线程,2处的sync就会一直等待永远都不会执行。
  • 如图-死锁3、死锁4
         

死锁3.png

         

死锁4.png




1 个评论

已赞

要回复文章请先登录注册