美文网首页iOS多线程相关
关于dispatch_sync死锁

关于dispatch_sync死锁

作者: 上发条的树 | 来源:发表于2018-12-03 16:10 被阅读2次

理解顺序

1、主线程有且只要一个队列,即主队列,用于UI刷新。通过这个dispatch_get_main_queue()可以获取主队列。

2、dispatch_sync因为是同步操作,需要等待block执行完成,才返回。

3、如果当前线程为主线程,传入队列为主队列,那么调用dispatch_sync即阻塞主队列,而block中又等待主队列的完成,主队列不完成,dispatch_sync也不返回,造成循环的等待,也就是死锁。


官方文档:

dispatch_sync(dispatch_queue_t queue, DISPATCH_NOESCAPE dispatch_block_t block);

将block中的内容提交给指定的队列,并同步执行:

Submits a block object for execution on a dispatch queue and waits until that block completes.

值得注意的:
将块提交给分派队列以进行同步执行。与dispatch_async不同,这个函数直到块完成才返回。调用此函数并针对当前队列会导致死锁。

Submits a block to a dispatch queue for synchronous execution. Unlike dispatch_async, this function does not return until the block has finished. Calling this function and targeting the current queue results in deadlock.

重要的事情:
current queue
current queue
current queue

这里着重理解“当前队列”,一般我们当前队列就是主线程的队列,也就是主队列:dispatch_get_main_queue(),也就是说,如果dispatch_sync传入的队列,不是当前队列,则不会出现死锁。

当前队列为主队列,直接这样写,会造成死锁:

- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"执行");
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"死锁,不执行");
    });
    NSLog(@"不执行");
}

执行结果:

2018-12-03 15:31:11.849985+0800 testtest[2581:512553] 执行,当前队列:<NSThread: 0x60000006d700>{number = 1, name = main}

如果dispatch_sync(dispatch_get_main_queue(), ^{});这种写法,放在的队列不是当前队列:

- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"1,当前队列:%@",[NSThread currentThread]);
    dispatch_queue_t queue = dispatch_queue_create("123", NULL);
     //切换当前队列为自定义的队列
    dispatch_async(queue, ^{
        NSLog(@"2,当前队列:%@",[NSThread currentThread]);
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"3,当前队列:%@",[NSThread currentThread]);
        });
    });
    NSLog(@"4");
}

执行结果:

2018-12-03 15:46:18.361870+0800 testtest[2731:536556] 1,当前队列:<NSThread: 0x6040000640c0>{number = 1, name = main}
2018-12-03 15:46:18.362098+0800 testtest[2731:536556] 4
2018-12-03 15:46:18.362177+0800 testtest[2731:536668] 2,当前队列:<NSThread: 0x60400047c9c0>{number = 4, name = (null)}
2018-12-03 15:46:18.404327+0800 testtest[2731:536556] 3,当前队列:<NSThread: 0x6040000640c0>{number = 1, name = main}

相同队列的操作:

- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"1,当前队列:%@",[NSThread currentThread]);
    dispatch_queue_t queue = dispatch_queue_create("123", NULL);
    dispatch_async(queue, ^{
        NSLog(@"2,当前队列:%@",[NSThread currentThread]);
        dispatch_sync(queue, ^{
            NSLog(@"3,当前队列:%@",[NSThread currentThread]);
        });
    });
    NSLog(@"4");
}

执行结果:

2018-12-03 16:12:15.326599+0800 testtest[2956:573733] 1,当前队列:<NSThread: 0x604000075180>{number = 1, name = main}
2018-12-03 16:12:15.326838+0800 testtest[2956:573733] 4
2018-12-03 16:12:15.326908+0800 testtest[2956:573835] 2,当前队列:<NSThread: 0x600000479380>{number = 4, name = (null)}

总结

因此,要知道dispatch_sync是否会死锁,需要知道当前队列和传入的队列是否是同一个。如果是同一个,才会造成死锁。而不是说,这样写:dispatch_sync(dispatch_get_main_queue(), ^{});就一定会死锁。

相关文章

  • 关于dispatch_sync死锁

    理解顺序 1、主线程有且只要一个队列,即主队列,用于UI刷新。通过这个dispatch_get_main_queu...

  • 关于dispatch_sync的死锁

    看源码的时候看到了sync的运用,故将于此有关的死锁按自己的想法理解一下 官方的解析 引用一下 这篇文章的说法: ...

  • 多线程进阶

    1.线程死锁问题 1) dispatch_sync(dispatch_get_main_queue(), ^{ ...

  • 死锁问题

    判断是否死锁 终极方法是判断死锁问题产生的根源是dispatch_sync 是否是发生在当前dispatch_s...

  • 面试题整理(一)

    1.堆和栈的区别 2.死锁问题 //死锁原因 dispatch_sync在等待block语句执行完成,而block...

  • GCD2

    1. 死锁 发生死锁原因:dispatch_sync会将任务追加到队列上,等当前的任务执行完毕,再执行Block中...

  • dispatch_sync死锁问题研究

    首先,看看如下代码的输出是什么? 首先答案是会发生死锁,我们看看官方文档关于dispatch_sync的解释: S...

  • GCD的基本语法

    //异步主线程运行,不会产生生死锁 dispatch_sync(dispatch_get_main_queue()...

  • 同步串行导致的死锁问题

    GCD中同步操作dispatch_sync()中队列使用主队列会导致线程死锁,是众所周知的事情。但是是如何造成死锁...

  • 多线程引起死锁的几种情况及解决办法

    1.第一种情况:dispatch_sync(dispatch_get_main_queue(), ^{}引起死锁 ...

网友评论

    本文标题:关于dispatch_sync死锁

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