Queue (隊(duì)列): 分為串行和并行, 串行隊(duì)列按順序開始執(zhí)行,? 執(zhí)行完上一個(gè)才能執(zhí)行下一個(gè). 并行隊(duì)列(開始也是按添加順序執(zhí)行,不需要等其他的完成) 允許同時(shí)執(zhí)行多個(gè)任務(wù), 完成的順序是隨機(jī)的
Async和Sync (異步執(zhí)行和同步執(zhí)行): 使用dispathc_async調(diào)用一個(gè)block, 這個(gè)block會(huì)被放到隊(duì)尾執(zhí)行,? 至于block是串行執(zhí)行還是并行執(zhí)行只和dispatch_async中的參數(shù)里面指定的queue是并行的還是串行的有關(guān),? 但是dispatch_async會(huì)馬上返回.
而dispatch_sync同樣也是把block放到指定的queue上面執(zhí)行, 但是會(huì)等待這個(gè)block執(zhí)行完畢才會(huì)返回, 阻塞當(dāng)前的queue直到sync返回
1. 所以, 當(dāng)前queue是串行隊(duì)列的時(shí)候
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"2");
});
這段代碼如果在主線程執(zhí)行的, 那么就會(huì)造成死鎖,? 因?yàn)閐ispatch_sync函數(shù)指定的線程和函數(shù)所在的都是主線程(dispatch_get_main_queue), 而dispatch_sync要dispatch_get_main_queue執(zhí)行完dispatch_sync中的block才會(huì)有返回,? 而dispatch_get_main_queue中又在執(zhí)行dispatch_sync這個(gè)函數(shù), 要等到dispatch_sync函數(shù)返回才回去執(zhí)行block. 這就造成了dispatch_sync永遠(yuǎn)都無法返回了(死鎖).
總結(jié):? 主要原因就在于dispatch_sync所在的線程和函數(shù)指定的線程是同一個(gè)線程,且是串行的.? 而串行隊(duì)列執(zhí)行原則是一個(gè)完成在執(zhí)行下一個(gè)的. 這就好比, 我們?nèi)ツ车刭I房,? 但是買房需要先有戶口,? 而想要戶口卻必須要有房子. 這就造成了你一輩子都沒辦法在這地方買房了.? 類比可能稍微有些不恰當(dāng), 但是大體是這個(gè)意思. 理解就好
會(huì)阻塞當(dāng)前線程(在這種情況是主線程), 而主線程被阻塞之后,? 因?yàn)閐ispatch_sync把block放到了主線程的隊(duì)尾, 因此, 主線程需要等dispatch_sync函數(shù)返回之后才會(huì)繼續(xù)執(zhí)行下去, 也就是去執(zhí)行block,? 而dispatch_sync 需要block執(zhí)行完畢才返回.? 因此,? 這個(gè)時(shí)候就會(huì)造成死鎖問題,
于此類似的
dispatch_queue_t queue1 = dispatch_queue_create("com.baizhong.queue1", DISPATCH_QUEUE_SERIAL); ?//串行
dispatch_async(queue1, ^{
NSLog(@"1");
dispatch_sync(queue1, ^{
NSLog(@"2");
});
});
NSLog(@"3");
上面這段代碼也會(huì)死鎖
因?yàn)閐ispatch_sync函數(shù)指定的線程和函數(shù)所在的線程都是queue1,? 而queue1 是串行隊(duì)列
下面就不會(huì)了
dispatch_queue_t queue = dispatch_queue_create("com.baizhong.queue1", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"1");
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"2");
});
});
NSLog(@"3");
因?yàn)閐ispatch_async所在的當(dāng)前線程和dispatch_async函數(shù)中指定的線程不是同一個(gè)
2. 當(dāng)前的queue是并行隊(duì)列的時(shí)候
第一種情況:
dispatch_queue_t queue2 = dispatch_queue_create("com.baizhong.queue1", DISPATCH_QUEUE_CONCURRENT); //并行
dispatch_async(queue2, ^{
NSLog(@"1");
dispatch_sync(queue2, ^{
NSLog(@"這種不會(huì)死鎖");
});
});
NSLog(@"3");
這種情況因?yàn)閝ueue是并行隊(duì)列,? 所以 NSLog(@"2")會(huì)馬上執(zhí)行,所以dispatch_sync函數(shù)也不會(huì)一直等待不返回造成死鎖
第二種情況:
dispatch_queue_t queue = dispatch_queue_create("com.baizhong.queue1", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"1");
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"這種不會(huì)死鎖");
});
});
NSLog(@"3");
這種也是一樣
總結(jié)起來就是:
造成死鎖的主要原因就是,在某一個(gè)串行隊(duì)列中, 同步的向這個(gè)隊(duì)列添加block.
上面列舉的只是一部分情況, 還有其他的各種情況可以自己動(dòng)手寫寫, 但是歸根結(jié)底原因都是差不多
關(guān)于隊(duì)列與線程
當(dāng)我們創(chuàng)建了隊(duì)列之后僵朗,我們需要把任務(wù)添加到隊(duì)列中灶芝,并指定以同步還是異步的方式執(zhí)行添加到隊(duì)列中的任務(wù)枷颊。
? ?同步霞掺,其會(huì)在當(dāng)前線程立即執(zhí)行添加的任務(wù)(無論是串行還是并行隊(duì)列都如此)箍镜。
? ?異步硫眨,其會(huì)新創(chuàng)建一個(gè)新的線程來執(zhí)行任務(wù)憨闰。而異步對(duì)于串行和并行隊(duì)列的又不一樣的意義的遇绞。
對(duì)于異步執(zhí)行的串行隊(duì)列的話,新添加的多個(gè)任務(wù)會(huì)在新創(chuàng)建的線程中依次執(zhí)行讼撒,即一個(gè)執(zhí)行完在執(zhí)行另一個(gè)任務(wù)浑厚,有點(diǎn)類似同步執(zhí)行的樣子(其區(qū)別可以看做是同步不會(huì)創(chuàng)建新的線程股耽,而異步會(huì)創(chuàng)建新的線程,且只創(chuàng)建一個(gè))钳幅。
如果是并發(fā)隊(duì)列的話物蝙,使用同步方式執(zhí)行任何則和串行隊(duì)列一樣。而使用異步方式執(zhí)行任務(wù)的話敢艰,新添加的任務(wù)都會(huì)放到新創(chuàng)建的線程诬乞,即每個(gè)任務(wù)在單獨(dú)線程中,并且所有的任務(wù)都是并發(fā)執(zhí)行的钠导,而不像串行隊(duì)列是有順序的震嫉。如果是異步方式執(zhí)行的話,則每個(gè)任務(wù)都會(huì)新開一個(gè)線程牡属,并且這些任務(wù)是并發(fā)執(zhí)行的票堵。
參考鏈接
歡迎指正!