之前看面試題知道下面代碼會死鎖,網(wǎng)上說是因為相互等待,等等,總覺得難以理解
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"死鎖了");
});
經(jīng)過一下午的仔細研究,算是有點收獲,下面分享給大家,不對的地方歡迎指正
一:首先介紹下基本概念
隊列:用于存放任務(wù)。一共有兩種隊列,串行隊列和并行隊列。
同步(sync)和異步(async)的主要區(qū)別在于會不會阻塞當前線程,直到Block中的任務(wù)執(zhí)行完畢!
如果是同步(sync)操作,它會阻塞當前線程并等待Block中的任務(wù)執(zhí)行完畢,然后當前線程才會繼續(xù)往下運行。
如果是異步(async)操作,當前線程會直接往下執(zhí)行,它不會阻塞當前線程
二:死鎖
官方文檔指出:dispatch_sync的當前執(zhí)行隊列與提交block執(zhí)行的目標隊列相同時將造成死鎖。
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.
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"死鎖了");
});
根據(jù)文檔所說,此任務(wù)本身(整個代碼)在主隊列中,而要添加的任務(wù)(NSLog(@"死鎖了");)也要添加到主隊列,它會死鎖。這是為什么呢?
假設(shè)自己為A任務(wù),A任務(wù)所在的隊列為主隊列,A任務(wù)正在執(zhí)行,A任務(wù)的代碼是添加B任務(wù)到主隊列并使B任務(wù)執(zhí)行完畢,然后B任務(wù)就被添加到主隊列,可是它要等待A任務(wù)執(zhí)行完,才輪到它執(zhí)行,A任務(wù)等待B任務(wù),B任務(wù)又等待A任務(wù),因此形成死鎖。
為了驗證觀點,我試了下面的代碼:
dispatch_queue_t queue =dispatch_queue_create("queue",DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
? ? ? ?NSLog(@"正常打印");
? ? ? dispatch_sync(queue, ^{
? ? ? ? ? ? ? ? ?NSLog(@"死鎖了");
? ? ? ? ? ? ? ? });
? ? ?});
NSLog(@"死鎖了");
因為是同步往“queue”添加任務(wù),可是本身又是在“queue”中執(zhí)行,再次循環(huán)等待,死鎖發(fā)生。
參考自鏈接:
https://www.zhihu.com/question/23338200/answer/57844956
http://www.itdecent.cn/p/0b0d9b1f1f19