關于dispatch_sync死鎖

理解順序

1、主線程有且只要一個隊列,即主隊列,用于UI刷新。通過這個dispatch_get_main_queue()可以獲取主隊列。

2、dispatch_sync因為是同步操作,需要等待block執(zhí)行完成,才返回。

3、如果當前線程為主線程,傳入隊列為主隊列,那么調(diào)用dispatch_sync即阻塞主隊列,而block中又等待主隊列的完成,主隊列不完成,dispatch_sync也不返回,造成循環(huán)的等待,也就是死鎖。


官方文檔:

dispatch_sync(dispatch_queue_t queue, DISPATCH_NOESCAPE dispatch_block_t block);

將block中的內(nèi)容提交給指定的隊列,并同步執(zhí)行:

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

值得注意的:
將塊提交給分派隊列以進行同步執(zhí)行。與dispatch_async不同,這個函數(shù)直到塊完成才返回。調(diào)用此函數(shù)并針對當前隊列會導致死鎖。

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傳入的隊列,不是當前隊列,則不會出現(xiàn)死鎖。

當前隊列為主隊列,直接這樣寫,會造成死鎖:

- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"執(zhí)行");
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"死鎖,不執(zhí)行");
    });
    NSLog(@"不執(zhí)行");
}

執(zhí)行結(jié)果:

2018-12-03 15:31:11.849985+0800 testtest[2581:512553] 執(zhí)行,當前隊列:<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");
}

執(zhí)行結(jié)果:

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");
}

執(zhí)行結(jié)果:

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)}

總結(jié)

因此,要知道dispatch_sync是否會死鎖,需要知道當前隊列和傳入的隊列是否是同一個。如果是同一個,才會造成死鎖。而不是說,這樣寫:dispatch_sync(dispatch_get_main_queue(), ^{});就一定會死鎖。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容