GCD多线程面试案例分析与结果

334 阅读2分钟
  • 案例1
- (void)interview01
{
    // 问题:以下代码是在主线程执行的,会不会产生死锁?会!
    NSLog(@"viewDid1");
    
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_sync(queue, ^{
        NSLog(@"执行任务2");
    });
    
    NSLog(@"ViewDid3");
    
    // dispatch_sync立马在当前线程同步执行任务
}

  • 结果 image.png

  • 分析 image.png

    • “执行任务2”任务添加到主队列(特殊的串行队列),当前线程是主线程,任务呗添加到主线程中执行
    • sync是不会开启新的线程。 同步串行
    • 所以会阻塞线程等待主线程中上一个任务完成后才能执行下一个任务。
    • dispatch_sync立马在当前线程同步执行任务,执行完毕才能往下执行。
    • 在任务1执行过程中要执行任务2,同时任务二执行完后还有剩余的任务1接着做,但是机器的逻辑是执行1完毕才能执行2,执行完2后才能继续执行剩余的任务1,导致了任务1和任务2在互相等待对方执行完毕。死锁了。
  • 案例2

- (void)interview02
{
    // 问题:以下代码是在主线程执行的,会不会产生死锁?不会!
    NSLog(@"执行任务1");
    
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_async(queue, ^{
        NSLog(@"执行任务2");
    });
    
    NSLog(@"执行任务3");
    
    // dispatch_async不要求立马在当前线程同步执行任务
}
  • 异步串行,没有开启新的线程
  • 结果 不会产生死锁。 image.png
  • 分析
    • viewdidLoad是任务1正在执行
    • 任务2加入,但是这个任务是异步执行,可以先等等的任务
    • 等任务1完成后再做任务2
    • 我这加了一个viewwillAppear 说明这个打印2是先等viewdidload执行完成后才执行的。 image.png
  • 案例3
- (void)interview03
{
    // 问题:以下代码是在主线程执行的,会不会产生死锁?会!
    NSLog(@"执行任务1");
    
    dispatch_queue_t queue = dispatch_queue_create("myqueu", DISPATCH_QUEUE_SERIAL);
    dispatch_async(queue, ^{ // 0
        NSLog(@"执行任务2");
        
        dispatch_sync(queue, ^{ // 1
            NSLog(@"执行任务3");
        });
    
        NSLog(@"执行任务4");
    });
    
    NSLog(@"执行任务5");
}
  • 结果 image.png
  • 分析
    • 这个分析与第一个类似

image.png

  • 案例4
{
    // 问题:以下代码是在主线程执行的,会不会产生死锁?不会!
    NSLog(@"执行任务1");
    //并发队列在运行的过程中会开启新的子线程来完成工作
    dispatch_queue_t queue2 = dispatch_queue_create("myqueu2", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue2, ^{ // 0
        NSLog(@"执行任务2");
        
        dispatch_sync(queue2, ^{ // 1
            NSLog(@"执行任务3");
        });
        
        NSLog(@"执行任务4");
    });
    
    NSLog(@"执行任务5");
}

image.png image.png

总结

在串行队列中同步执行任务时,在一个任务中不要同步加入新的任务,这样会产生死锁。

队列

dispatch_queue_t queue1 = dispatch_get_global_queue(0, 0);
dispatch_queue_t queue2 = dispatch_get_global_queue(0, 0);
dispatch_queue_t queue3 = dispatch_queue_create("queu3", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t queue4 = dispatch_queue_create("queu4", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t queue5 = dispatch_queue_create("queu5", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t queue6 = dispatch_queue_create("queu6", DISPATCH_QUEUE_SERIAL);

image.png

  • 全局并发队列
  • 并发队列
  • 串行队列