美文网首页
GCD dead lock 试分析

GCD dead lock 试分析

作者: nunca | 来源:发表于2018-03-28 17:21 被阅读0次
    • 基本概念:

    一、dispatch queue 种类
    1.serial dispatch queue : 等待现在执行中的处理结束,同时执行的处理数只能有1个

    // 新建一个serial dispatch queue
    dispatch_queue_t serialQueue = dispatch_queue_create("serial.queue.Async", NULL);
    
    // 获取main dispatch queue
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    

    2.concurrent dispatch queue : 不等待现在执行中的处理结束,可同时进行多个处理,由当前系统的状态决定并行执行的处理数

    // 新建一个concurrent dispatch queue
    dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrent.queue.Sync", DISPATCH_QUEUE_CONCURRENT);
    
    // 获取global dispatch queue
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    

    二、dispatch_sync 和dispatch_async 函数
    1.dispatch_sync:即为同步,也就是将指定的block同步追加到指定的dispatch queue中,在追加block结束之前,dispatch_sync函数会一直等待

      dispatch_queue_t queue = dispatch_queue_create("concurrent.queue.Async", DISPATCH_QUEUE_CONCURRENT);
      dispatch_sync(queue, ^{
          for (int i = 0 ; i < 5; i ++ ) {NSLog(@"--sync----task1----%d",i);}
      });
      dispatch_sync(queue, ^{
          for (int i = 0 ; i < 5; i ++ ) {NSLog(@"--sync----task2----%d",i);}
      });
      dispatch_sync(queue, ^{
          for (int i = 0 ; i < 5; i ++ ) {NSLog(@"--sync----task3----%d",i);}
      });
    

    如下打印,task1、task2、task3 按顺序依次执行,在task1未结束之前dispatch_sync函数会进行等待

    2018-03-28 16:15:40.658351+0800 Nunca[8534:179897] --sync----task1----0
    2018-03-28 16:15:40.658539+0800 Nunca[8534:179897] --sync----task1----1
    2018-03-28 16:15:40.658802+0800 Nunca[8534:179897] --sync----task1----2
    2018-03-28 16:15:40.658923+0800 Nunca[8534:179897] --sync----task1----3
    2018-03-28 16:15:40.659021+0800 Nunca[8534:179897] --sync----task1----4
    2018-03-28 16:15:40.659511+0800 Nunca[8534:179897] --sync----task2----0
    2018-03-28 16:15:40.659939+0800 Nunca[8534:179897] --sync----task2----1
    2018-03-28 16:15:40.660690+0800 Nunca[8534:179897] --sync----task2----2
    2018-03-28 16:15:40.661190+0800 Nunca[8534:179897] --sync----task2----3
    2018-03-28 16:15:40.661645+0800 Nunca[8534:179897] --sync----task2----4
    2018-03-28 16:15:40.662288+0800 Nunca[8534:179897] --sync----task3----0
    2018-03-28 16:15:40.662472+0800 Nunca[8534:179897] --sync----task3----1
    2018-03-28 16:15:40.663441+0800 Nunca[8534:179897] --sync----task3----2
    2018-03-28 16:15:40.664091+0800 Nunca[8534:179897] --sync----task3----3
    2018-03-28 16:15:40.664344+0800 Nunca[8534:179897] --sync----task3----4
    

    2.dispatch_async:即为非同步,就是将指定的block非同步地追加到指定的dispatch queue中,dispatch_async函数不做等待

      dispatch_queue_t queue = dispatch_queue_create("concurrent.queue.Async", DISPATCH_QUEUE_CONCURRENT);
      dispatch_async(queue, ^{
          for (int i = 0 ; i < 5; i ++ ) {NSLog(@"--Async----task1----%d",i);}
      });
      dispatch_async(queue, ^{
          for (int i = 0 ; i < 5; i ++ ) {NSLog(@"--Async----task2----%d",i);}
      });
      dispatch_async(queue, ^{
          for (int i = 0 ; i < 5; i ++ ) {NSLog(@"--Async----task3----%d",i);}
      });
    

    如下打印,task1、task2、task3 并列同步执行,不用等待task1执行完成便可开始执行task2、task3

    2018-03-28 16:13:25.517938+0800 Nunca[8470:178300] --Async----task2----0
    2018-03-28 16:13:25.517938+0800 Nunca[8470:178303] --Async----task1----0
    2018-03-28 16:13:25.517957+0800 Nunca[8470:178299] --Async----task3----0
    2018-03-28 16:13:25.518208+0800 Nunca[8470:178300] --Async----task2----1
    2018-03-28 16:13:25.518219+0800 Nunca[8470:178303] --Async----task1----1
    2018-03-28 16:13:25.518420+0800 Nunca[8470:178300] --Async----task2----2
    2018-03-28 16:13:25.518420+0800 Nunca[8470:178299] --Async----task3----1
    2018-03-28 16:13:25.518495+0800 Nunca[8470:178300] --Async----task2----3
    2018-03-28 16:13:25.518524+0800 Nunca[8470:178303] --Async----task1----2
    2018-03-28 16:13:25.518674+0800 Nunca[8470:178299] --Async----task3----2
    2018-03-28 16:13:25.518753+0800 Nunca[8470:178303] --Async----task1----3
    2018-03-28 16:13:25.519352+0800 Nunca[8470:178300] --Async----task2----4
    2018-03-28 16:13:25.519569+0800 Nunca[8470:178299] --Async----task3----3
    2018-03-28 16:13:25.519778+0800 Nunca[8470:178303] --Async----task1----4
    2018-03-28 16:13:25.520527+0800 Nunca[8470:178299] --Async----task3----4
    
    • Dead lock:

    虽然实际写代码时 serial queue + sync task 的组合基本不会出现,但还是可以记录下此种情况下容易导致发生的死锁问题。

    casa 1 :

        dispatch_queue_t queue = dispatch_get_main_queue();
        dispatch_sync(queue, ^{
            NSLog(@"dead lock");
        });
    

    如上,试分析:
    1、dispatch_sync()函数在主线程执行,传入的block也需要添加到主线程并在主线程执行,因此主线程现在有两个任务需要执行 :task1 dispatch_sync() 、 task2 block() ;
    2、由于main dispatch queue 为serial dispatch queue ,所以需要等待task1处理结束才能处理task2;
    3、对于task1 dispatch_sync函数,由于sync代表的同步性,必须等到追加的block(task2)执行结束 dispatch_sync函数才会返回,在追加block结束之前,dispatch_sync函数会一直等待;

    所以此时的情况是:task1执行完成 task2才能开始执行、task2结束task1才能执行完成,死锁便出现。

    case 2 :

        dispatch_queue_t serialQueue = dispatch_queue_create("serial.queue.Async", NULL);
        dispatch_async(serialQueue, ^{ // block1
            dispatch_sync(serialQueue, ^{ //block2
                NSLog(@"dead lock");
            });
        });
    

    试分析:
    1、在主线程中执行dispatch_async()函数,在serialQueue中需要执行的任务有:task1 block1() 、task2 block2() ;
    2、block1中内容即为dispatch_sync()函数,因此task1 实际为dispatch_sync() ;
    3、同case1

    相关文章

      网友评论

          本文标题:GCD dead lock 试分析

          本文链接:https://www.haomeiwen.com/subject/hltucftx.html