iOS底层探索--GCD-函数与队列

432 阅读3分钟

小谷底层探索合集

  • 在研究GCD前,先来一篇函数与队列,这样,GCD就更容易理解了

1. 概念篇

1.1. GCD中的函数

    1. 任务使用 block 封装
    1. 任务的 block 没有参数也没有返回值
    1. 执行任务的函数
    • 3.1. 异步 dispatch_async

    不用等待当前语句执行完毕,就可以执行下一条语句

    会开启线程执行 block 的任务

    异步是多线程的代名词

    • 3.2. 同步 dispatch_sync

    必须等待当前语句执行完毕,才会执行下一条语句

    不会开启线程

    在当前执行 block 的任务

1.2. 队列

    1. 关于队列,有一幅比较形象的图:
    1. 串行队列分析:就是要排队,就一个通道:FIFO(先进先出)
    1. 并行队列分析:假设在窗口买饭,有4个窗口,没准谁先买完

感觉换成吃的,比较好理解~~

1.3. 函数与队列的结合

    1. 同步函数串行队列

    1. 不会开启线程,在当前线程执行任务
    2. 任务串行执行,任务一个接着一个
    3. 会产生堵塞
    1. 同步函数并发队列

    1. 不会开启线程,在当前线程执行任务
    2. 任务一个接着一个
    1. 异步函数串行队列

    1. 开启一条新线程
    2. 任务一个接着一个
    1. 异步函数并发队列

    1. 开启线程,在当前线程执行任务
    2. 任务异步执行,没有顺序,和CPU调度有关

2. 应用

  • 在函数和队列的运用,就通过面试题讲解(听说面试考量比较多)

2.1. 面试题1

  • 写出下面程序输出
- (void)textDemo1{
    dispatch_queue_t queue = dispatch_queue_create("question1", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"1");
    dispatch_async(queue, ^{
        NSLog(@"2");
        dispatch_sync(queue, ^{
            NSLog(@"3");
        });
        NSLog(@"4");
    });
    NSLog(@"5");

}

分析:

  1. 这个是个并行队列
  2. 无论是同步还是异步都是耗时的
  3. 所以先出来的是主队列的 1-5
  4. 在并行队列中是同步队列,所以依次执行

答案:1-5-2-3-4

2.2. 面试题2

  • 写出下面程序输出
- (void)textDemo2{
    // 同步队列
    dispatch_queue_t queue = dispatch_queue_create("question2", NULL);
    NSLog(@"1");
    // 异步函数
    dispatch_async(queue, ^{
        NSLog(@"2");
        // 同步
        dispatch_sync(queue, ^{
            NSLog(@"3");
        });
        NSLog(@"4");
    });
    NSLog(@"5");
}

分析

  1. 这个是串行队列: #define DISPATCH_QUEUE_SERIAL NULL
  2. 先出来的是主队列的 1-5
  3. 然后输出 2.
  4. 之后大家就比较迷茫了。我画了个图:
  5. 块任务添加3任务,然后3任务等待4任务执行完,4任务等待块任务执行完,块任务等待3任务执行完
  6. 这样就形成了死锁

答案: 1-5-2-卡住

2.3. 面试题3

  • 选择题:以下程序输出可能是()

    A : 1230789

    B : 1237890

    C : 3120798

    D : 2137890

- (void)textDemo3{
    dispatch_queue_t queue = dispatch_queue_create("question3", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{ 
        NSLog(@"1");
    });
    dispatch_async(queue, ^{
        NSLog(@"2");
    });
    
    dispatch_sync(queue, ^{
        NSLog(@"3");
    });
    
    NSLog(@"0");

    dispatch_async(queue, ^{
        NSLog(@"7");
    });
    dispatch_async(queue, ^{
        NSLog(@"8");
    });
    dispatch_async(queue, ^{
        NSLog(@"9");
    });
    
}

分析:

  1. 这是一个并行队列异步线程 1 2同步线程3不能确定谁先执行完
  2. 3任务同步线程,所以,3肯定在0 前面
  3. 7-8-9任务异步线程,所以没有顺序,但是肯定在0之后

答案: AC