GCD 死锁

参考:http://ios.jobbole.com/82622/


并发队列只能决定“是否”可以同时调度多个任务,不会决定开不开线程,并发队列的并发功能只有内部的任务是异步任务时,才有效。

同步的方式执行任务:在当前线程中依次执行任务。dispatch_sync()

异步的方式执行任务:新开线程在新线程中执行任务。dispatch_async()


GCD死锁原理

    1.串行队列与并发队列:在使用GCD的时候,我们把需要处理的任务放到block中,然后将任务追加到相应的队列里面。这个队列叫做Dispatch Queue。存在两种Dispatch Queue一种是要等待上一个执行完,在执行下一个的Serial Dispatch Queue,这种叫做串行队列。另一种则是不需要上一个执行完,就能执行下一个的Concurrent Dispatch Queue,叫做并发队列。这两种,均遵循FIFO原则。

    2.并发与并行的区别:当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程。它只能把CPU运行时间划分成若干个时间段,再将时间段分配给各个线程执行,在一个时间段的线程代码运行时,其他线程处于挂起状态,这种方式我们称之为并发。      当系统有一个以上CPU时,则线程的操作有可能非并发,当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行。

    3.同步与异步:串行与并发针对的是队列,而同步与异步针对的是线程。最大的区别在于,同步线程要阻塞当前线程,必须要等待同步线程中的任务执行完,返回以后,才能继续下一个任务;而异步线程则是不用等待。

    4.系统提供的两个队列:全局队列,也是一个并发队列 dispatch_get_global_queue   主队列,在主线程中运行,因为主线程只有一个,所以这是一个串行队列 dispatch_get_main_queue

     5.自己创建的队列:

    dispatch_queue_t serialQueue = dispatch_queue_create("com.dlg.serial",DISPATCH_QUEUE_SERIAL);//串行队列

    dispatch_queue_t concurrentQueue =dispatch_queue_create("com.dlg.concurrent",DISPATCH_QUEUE_CONCURRENT);//并发队列

    6.同步与异步线程的创建:  dispatch_sync(...,^(block))  同步线程。dispatch_async(..., ^(block)) 异步线程。

 注意:一个任务可以是一个函数(function)或者是一个block!!!!

       7.案例分析一(死锁):

    NSLog(@"1");//任务一
    dispatch_sync(dispatch_get_main_queue(), ^{  //同步线程(也是一个任务 可记做任务四)
        NSLog(@"2");//任务二
    });
    NSLog(@"3");//任务三 

控制台输出: 1


首先在主队列中(串行队列)任务一 nslog方法 、任务四   dispatch_sync方法、任务三  nslog方法   依次加入到主队列中 。当执行任务一的时候输出 1,当执行到任务四的时候  系统把任务四中的任务二(block块)放到主队列的队尾即任务三的后边。   要执行完任务四就必须等待block执行完后才能返回执行任务三。 最终的情况是,因为主队列在主线程中运行,主线程卡在了任务四上,要想执行完任务四,就必须执行完任务二(block)但是任务二在任务三的后面,需要等任务三执行完成才能执行到任务二。从而就产生了死锁。


注意:下边函数的行为就是把任务二加入到主队列中。

dispatch_sync(dispatch_get_main_queue(), ^{  //同步线程(也是一个任务 可记做任务四)
        NSLog(@"2");//任务二
    });


      8.案例分析二:

   NSLog(@"1"); // 任务1
   dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    NSLog(@"2"); // 任务2
   });
   NSLog(@"3"); // 任务3
     控制台输出: 1  2  3
请大家先思考下为什么输出顺序是1 2 3   ???



首先在主队列中(串行队列)任务一 nslog方法 、任务四   dispatch_sync方法、任务三  nslog方法   依次加入到主队列中 。当执行任务一的时候输出 1,当执行到任务四的时候系统把任务四中的任务二(block块)加入到全局队列(属于并发队列)中,并且阻塞,等待任务二执行完成并返回。当打印 2后,任务四执行完成,然后在执行任务三。


 9.案例分析三:

    dispatch_queue_t queue = dispatch_queue_create("com.demo.serialQueue", DISPATCH_QUEUE_SERIAL);
    NSLog(@"1"); // 任务1
    dispatch_async(queue, ^{
        NSLog(@"2"); // 任务2
        dispatch_sync(queue, ^{
            NSLog(@"3"); // 任务3
        });
        NSLog(@"4"); // 任务4
    });
    NSLog(@"5"); // 任务5
    //输出: 1  5  2

首先在主队列中( 串行队列 )将任务一 nslog方法 、任务六  dispatch_async方法、任务五 slog方法、   依次加入到主队列中 。当执行任务一的时候输出 1,当执行任务六的时候 系统把任务六中的block加入到主队列中然后执行了任务五,输出5,因为任务二排在了任务五之后,然后输出 2 ,接下来执行任务七 dispatch_sync方法,系统把任务七中的block加到了主队列的队尾处,要想执行完任务三,所以就必须执行完排在它前边的任务四, 因为是同步执行所以任务七等待block(任务三)执行完成才能执行任务四,然而任务四必须等任务七执行完成才能执行所以又出现了死锁。



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值