理解GCD死锁

1,413 阅读2分钟
先了解GCD 同步异步
  • dispatch_async异步执行任务的函数。

    • 不用等待当前语句执行完毕,就可以执行下一条语句。
    • 会开启线程执行block的任务。
    • 异步是多线程的代名词。
  • dispatch_sync同步函数。

    • 必须等待当前语句执行完毕,才会执行下一条语句。
    • 不会开启线程。
    • 在当前执行block任务。
  • block块是在函数内部执行的。

正常代码如下

先创建一个并发队列 加到异步函数中,里面有三个任务。分别是NSLog(@"2");``Block块 NSLog(@"4"); 代码:

dispatch_queue_t queue = dispatch_queue_create("bobo", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"1");
    dispatch_async(queue, ^{
        NSLog(@"2");
        dispatch_sync(queue, ^{
           NSLog(@"3");
        });
        NSLog(@"4");
    });
    NSLog(@"5");

结果如下 结果是 1 5 2 3 4

image.png

结果分析:

代码从上向下执行,先输出1,因为是异步函数,不会出现线程等待护犊子)所以会继续输出5,然后执行异步函数内执行任务 先输出2,然后遇到同步函数必须等待当前语句执行完毕,才会执行下一条语句,所以先执行完Block代码块才能执行4 所以先输出3 在输出4`

GCD死锁代码

将上面的代码并发改成串行 代码如下:

// 并发队列 DISPATCH_QUEUE_CONCURRENT
// 串行队列 DISPATCH_QUEUE_SERIAL  死锁
    dispatch_queue_t queue = dispatch_queue_create("bobo", DISPATCH_QUEUE_SERIAL);
    NSLog(@"1");
    dispatch_async(queue, ^{
        NSLog(@"2");
        dispatch_sync(queue, ^{
            NSLog(@"3");
        });
        NSLog(@"4");
    });
    NSLog(@"5");

结果如下 结果是 1 5 2 死锁

image.png 结果分析:

先执行任务1,串行队列,再执行异步函数异步函数不用的等待,执行5任务,再执行异步函数,因为是串行(FIFO),先进先出原则,先执行 2 任务,再执行block块任务,再执行4任务,因为block块是同步函数(必须等待当前语句执行完毕,才会执行下一条语句),所以先执行block块,block块又添加了3任务到队列后面,串行队列任务现在是 任务2任务block,任务4任务3 ,又因为4任务在3任务前面,所以3要等4任务结束,4要等block块结束 block 要等3任务结束 才走4,所以就出现了死锁(dispatch_sync_slow)的现象