iOS - 同步異步、串行并行

同步、異步:表示開(kāi)辟新線程的能力。
串行、并行:表示隊(duì)列的調(diào)度任務(wù)的能力。

任務(wù):就是執(zhí)行操作的意思,換句話說(shuō)就是你在線程中執(zhí)行的那段代碼。在 GCD 中是放在 block 中的。執(zhí)行任務(wù)有兩種方式:『同步執(zhí)行』 和 『異步執(zhí)行』。兩者的主要區(qū)別是:是否等待隊(duì)列的任務(wù)執(zhí)行結(jié)束,以及是否具備開(kāi)啟新線程的能力。

同步執(zhí)行(sync):
–同步添加任務(wù)到指定的隊(duì)列中,在添加的任務(wù)執(zhí)行結(jié)束之前,會(huì)一直等待,直到隊(duì)列里面的任務(wù)完成之后再繼續(xù)執(zhí)行。
–只能在當(dāng)前線程中執(zhí)行任務(wù),不具備開(kāi)啟新線程的能力。
異步執(zhí)行(async)
–異步添加任務(wù)到指定的隊(duì)列中,它不會(huì)做任何等待,可以繼續(xù)執(zhí)行任務(wù)。
–可以在新的線程中執(zhí)行任務(wù),具備開(kāi)啟新線程的能力。

注意:異步執(zhí)行雖然具有開(kāi)啟新線程的能力,但是并不一定開(kāi)啟新線程。這跟任務(wù)所指定的隊(duì)列類(lèi)型有關(guān)。

隊(duì)列(Dispatch Queue):這里的隊(duì)列指執(zhí)行任務(wù)的等待隊(duì)列,即用來(lái)存放任務(wù)的隊(duì)列。隊(duì)列是一種特殊的線性表,采用 FIFO(先進(jìn)先出)的原則,即新任務(wù)總是被插入到隊(duì)列的末尾,而讀取任務(wù)的時(shí)候總是從隊(duì)列的頭部開(kāi)始讀取。

串行隊(duì)列(Serial Dispatch Queue):
– 每次只有一個(gè)任務(wù)被執(zhí)行。讓任務(wù)一個(gè)接著一個(gè)地執(zhí)行。(只開(kāi)啟一個(gè)線程,一個(gè)任務(wù)執(zhí)行完畢后,再執(zhí)行下一個(gè)任務(wù))
并發(fā)隊(duì)列(Concurrent Dispatch Queue):
-可以讓多個(gè)任務(wù)并發(fā)(同時(shí))執(zhí)行。(可以開(kāi)啟多個(gè)線程,并且同時(shí)執(zhí)行任務(wù))
注意:并發(fā)隊(duì)列 的并發(fā)功能只有在異步(dispatch_async)方法下才有效。

『主線程』中,『不同隊(duì)列』+『不同任務(wù)』簡(jiǎn)單組合的區(qū)別:

622de264d90340e3bc62c70251093c53.png
  • 注意:從上邊可看出: 『主線程』 中調(diào)用 『主隊(duì)列』+『同步執(zhí)行』 會(huì)導(dǎo)致死鎖問(wèn)題。這是因?yàn)?主隊(duì)列中追加的同步任務(wù) 和 主線程本身的任務(wù) 兩者之間相互等待,阻塞了 『主隊(duì)列』,最終造成了主隊(duì)列所在的線程(主線程)死鎖問(wèn)題。
    而如果我們?cè)?『其他線程』 調(diào)用 『主隊(duì)列』+『同步執(zhí)行』,則不會(huì)阻塞 『主隊(duì)列』,自然也不會(huì)造成死鎖問(wèn)題。最終的結(jié)果是:不會(huì)開(kāi)啟新線程,串行執(zhí)行任務(wù)。

除了上邊提到的『主線程』中調(diào)用『主隊(duì)列』+『同步執(zhí)行』會(huì)導(dǎo)致死鎖問(wèn)題。實(shí)際在使用『串行隊(duì)列』的時(shí)候,也可能出現(xiàn)阻塞『串行隊(duì)列』所在線程的情況發(fā)生,從而造成死鎖問(wèn)題。這種情況多見(jiàn)于同一個(gè)串行隊(duì)列的嵌套使用。

比如下面代碼這樣:在『異步執(zhí)行』+『串行隊(duì)列』的任務(wù)中,又嵌套了『當(dāng)前的串行隊(duì)列』,然后進(jìn)行『同步執(zhí)行』。

dispatch_queue_t queue = dispatch_queue_create("test.queue", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{ // 異步執(zhí)行 + 串行隊(duì)列
dispatch_sync(queue, ^{ // 同步執(zhí)行 + 當(dāng)前串行隊(duì)列
// 追加任務(wù) 1
[NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
NSLog(@"1---%@",[NSThread currentThread]); // 打印當(dāng)前線程
});
});

執(zhí)行上面的代碼會(huì)導(dǎo)致 串行隊(duì)列中追加的任務(wù) 和 串行隊(duì)列中原有的任務(wù) 兩者之間相互等待,阻塞了『串行隊(duì)列』,最終造成了串行隊(duì)列所在的線程(子線程)死鎖問(wèn)題。
主隊(duì)列造成死鎖也是基于這個(gè)原因,所以,這也進(jìn)一步說(shuō)明了主隊(duì)列其實(shí)并不特殊。

關(guān)于 『隊(duì)列中嵌套隊(duì)列』這種復(fù)雜情況,這里也簡(jiǎn)單做一個(gè)總結(jié)。不過(guò)這里只考慮同一個(gè)隊(duì)列的嵌套情況

『不同隊(duì)列』+『不同任務(wù)』 組合,以及 『隊(duì)列中嵌套隊(duì)列』 使用的區(qū)別:


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

相關(guān)閱讀更多精彩內(nèi)容

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