关于dispatch_sync死锁

理解顺序

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] 执行,当前队列:{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,当前队列:{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,当前队列:{number = 4, name = (null)}
2018-12-03 15:46:18.404327+0800 testtest[2731:536556] 3,当前队列:{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,当前队列:{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,当前队列:{number = 4, name = (null)}

总结

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

你可能感兴趣的:(关于dispatch_sync死锁)