美文网首页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死锁

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