美文网首页iOS 开发 Objective-C
iOS 底层 day19 多线程基本概念 GCD线程死锁总结

iOS 底层 day19 多线程基本概念 GCD线程死锁总结

作者: 望穿秋水小作坊 | 来源:发表于2020-09-14 17:27 被阅读0次

    一. 关于多线程中的一些基本概念

    1. iOS 中有几种多线程方案有哪几种?分别简述一下。
    主要记住 GCD 和 NSOperation 部分

    二. GCD 中的一些基本概念 和 线程死锁总结

    1. GCD 中有 2 个用来执行任务的函数
    • 同步 的方式来执行任务:
    dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
    
    • 异步 的方式来执行任务:
    dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
    
    2. 比较容易混淆的术语
    • 同步异步 主要影响:能不能开启新的线程
    • 同步:在当前线程执行任务,不具备开启新线程的能力
    • 异步:在新的线程执行任务,具备开启新线程的能力
    • 并发串行 主要影响:任务的执行方式
    • 并行多个任务并发(同时)执行
    • 串行一个执行完毕后,再执行下一个任务
    图解两者关系

    三. GCD 中一些串行、并行、同步、异步的问题

    1. 下面代码会造成死锁吗?
    - (void)viewDidLoad {
        [super viewDidLoad];
        NSLog(@"任务1");
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"任务2");
        });
        NSLog(@"任务3");
    }
    
    • 会死锁
    • 仅打印 任务1
    • 可以将 viewDidLoad 看成一个大任务,大任务已经在主队列(串行队列)的头部执行了,串行队列的特点是先进先出
    • 这时候,我们又往 主队列(串行队列) 里面塞了个 任务2的block ,在主队列(串行队列)任务二必须等大任务执行完毕。
    • 但是 大任务执行到 dispatch_sync ,又要求必须先执行 任务2的block,这样就引发矛盾了,就形成了死锁。
    2. 下面代码会造成死锁吗?
    - (void)viewDidLoad {
        [super viewDidLoad];
        NSLog(@"任务一");
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"任务二");
        });
        NSLog(@"任务三");
    }
    
    • 不会
    • 日志 任务一 任务三 任务二
    3. 下面代码会造成死锁吗?
    - (void)viewDidLoad {
        [super viewDidLoad];
        NSLog(@"任务一");
        dispatch_queue_t queue = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
        dispatch_async(queue, ^{
            NSLog(@"任务二");
            dispatch_sync(queue, ^{
                NSLog(@"任务三");
            });
            NSLog(@"任务四");
        });
        NSLog(@"任务五");
    }
    
    • 会死锁
    • 日志:任务一 任务五 任务二
    4. 下面代码会造成死锁吗?
    - (void)viewDidLoad {
        [super viewDidLoad];
        NSLog(@"任务一");
        dispatch_queue_t queue = dispatch_queue_create("queue1", DISPATCH_QUEUE_CONCURRENT);
        dispatch_async(queue, ^{
            NSLog(@"任务二");
            dispatch_sync(queue, ^{
                NSLog(@"任务三");
            });
            NSLog(@"任务四");
        });
        NSLog(@"任务五");
    }
    
    • 不会死锁
    • 日志:任务一 任务五 任务二 任务三 任务四
    5. 下面代码会造成死锁吗?
    - (void)viewDidLoad {
        [super viewDidLoad];
        NSLog(@"任务一");
        dispatch_queue_t queue = dispatch_queue_create("queue1", DISPATCH_QUEUE_CONCURRENT);
        dispatch_sync(queue, ^{
            NSLog(@"任务二");
            dispatch_sync(queue, ^{
                NSLog(@"任务三");
            });
            NSLog(@"任务四");
        });
        NSLog(@"任务五");
    }
    
    • 不会死锁
    • 日志:任务一 任务二 任务三 任务四 任务五

    四. 本章最重要:一句话 来判断是否造成死锁?

    使用 Sync 函数往当前串行队列中添加任务,会卡主当前的串行队列(产生死锁)

    相关文章

      网友评论

        本文标题:iOS 底层 day19 多线程基本概念 GCD线程死锁总结

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