iOS线程死锁

作者: nucky_lee | 来源:发表于2019-02-15 23:15 被阅读58次

使用sync/async和queue的各种搭配时,常常有产生死锁崩溃的情况,现简单介绍几种死锁场景。

例一

- (void)viewDidLoad
{
   NSLog(@"---1");
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"---2");
    });
    NSLog(@"---3");
});

打印了1,并不会打印2和3,会死锁崩溃,因为dispatch_sync是同步,会阻塞当前主线程,等代码块里面内容执行完后再往下继续执行,然而根据dispatch_get_main_queue判断,代码块内的代码又需在主线程中执行,主线程已被阻塞了,所以代码块处于永远等待中。

例二

- (void)viewDidLoad {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"----1");
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"----2");
        });
        NSLog(@"---3");
    });
    NSLog(@"---4");
     while (YES) {}
}

2和3永远不会被打印,因为1在异步子线程中执行,所以可能1比4先打印。
这种情况下,因为2需要在主线程中同步执行,当打印了1后,把异步代码放到后台等待获取主线程,先执行4。然而遇到个死循环阻塞了主线程,而2又需要主线程才能执行,所以2处于永远等待获取主线程。

例三

dispatch_queue_t queue = dispatch_queue_create("com.demo.serialQueue", DISPATCH_QUEUE_SERIAL);
NSLog(@"1");
    dispatch_async(queue, ^{
        NSLog(@"2");
        dispatch_sync(queue, ^{
                    NSLog(@"3");
                });
        NSLog(@"4");
    });
     NSLog(@"5");

3和4永远不会被打印被锁死,3(dispatch_sync)同步等待dispatch_async这个代码块执行完再执行。而3又被dispatch_sync阻塞,且加入到队列任务尾部,等待队列queue里的任务执行执行完后再执行。

在看一个正常的场景:

NSLog(@"1"); // 任务1
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"2"); // 任务2
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"3"); // 任务3
        });
        NSLog(@"4"); // 任务4
    });
    NSLog(@"5");
分析:

首先,将【任务1、异步线程、任务5】加入Main Queue中,异步线程中的任务是:【任务2、同步线程、任务4】。

所以,先执行任务1,然后将异步线程中的任务加入到Global Queue中,因为异步线程,所以任务5不用等待,结果就是2和5的输出顺序不一定。

然后再看异步线程中的任务执行顺序。任务2执行完以后,遇到同步线程。将同步线程中的任务加入到Main Queue中,这时加入的任务3在任务5的后面。

当任务3执行完以后,没有了阻塞,程序继续执行任务4。

从以上的分析来看,得到的几个结果:1最先执行;2和5顺序不一定;4一定在3后面。

总结:

同步(sync) 和 异步(async) 的主要区别在于会不会阻塞当前线程,直到 Block 中的任务执行完毕!
如果是 同步(sync) 操作,它会阻塞当前线程并等待 Block 中的任务执行完毕,然后当前线程才会继续往下运行。
如果是 异步(async)操作,当前线程会直接往下执行,它不会阻塞当前线程。

根据queue判断是否新建线程/还是当前线程执行。


image.png

链接:https://www.jianshu.com/p/0b0d9b1f1f19

相关文章

  • 死锁 GCD 多线程

    死锁 GCD 多线程 Ios - LDSmallCat - 博客园 Ios中GCD死锁困扰很多人,分享一点个人经...

  • iOS线程死锁

    结论:使用sync函数往当前串行队列中添加任务,会卡住当前的串行队列(产生死锁) 首先你要理解同步和异步执行的概念...

  • iOS线程死锁

    使用sync/async和queue的各种搭配时,常常有产生死锁崩溃的情况,现简单介绍几种死锁场景。 例一 打印了...

  • JavaEE面试题总结 Day39 2018-12-29

    什么是线程死锁?死锁如何产生?如何避免线程死锁? 死锁的介绍: 线程死锁是指由于两个或者多个线程互相持有对方所需要...

  • iOS中的网络和多线程编程(六)

    摘自《iOS程序员面试笔试宝典》 什么是线程死锁 在讲解线程死锁前,首先看下面代码有什么问题? 在上述代码中,ma...

  • 2019 iOS面试题-----进程、线程、多进程、多线程、任务

    2019 iOS面试题-----多线程相关之GCD、死锁、dispatch_barrier_async、dispa...

  • iOS 10线程死锁

    今天,项目在iOS 10 上运行遇到线程死锁,后台进前台就死锁,导致ui卡死,在点击授权的alert也会卡死,比如...

  • iOS-知识点

    五个案例让你明白GCD死锁:http://ios.jobbole.com/82622/ iOS开发中多线程间关于锁...

  • Python中的各种锁

    Python之死锁 死锁分为两种情况,多进程/线程的死锁.或者是单线程的死锁. 1.首先看一下单线程的死锁,单线程...

  • 5. 死锁

    线程死锁 死锁是两个或更多线程阻塞着等待其它处于死锁状态的线程所持有的锁。死锁通常发生在多个线程同时但以不同的顺序...

网友评论

    本文标题:iOS线程死锁

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