多線程 GCD

GCD?

Serial vs. Concurrent 串行 vs. 并發(fā)

這些術(shù)語(yǔ)描述當(dāng)任務(wù)相對(duì)于其它任務(wù)被執(zhí)行,任務(wù)串行執(zhí)行就是每次只有一個(gè)任務(wù)被執(zhí)行铃肯,任務(wù)并發(fā)執(zhí)行就是在同一時(shí)間可以有多個(gè)任務(wù)被

執(zhí)行患亿。

在 GCD 中,這些術(shù)語(yǔ)描述當(dāng)一個(gè)函數(shù)相對(duì)于另一個(gè)任務(wù)完成押逼,此任務(wù)是該函數(shù)要求 GCD 執(zhí)行的步藕。一個(gè)_同步_函數(shù)只在完成了它預(yù)定的任務(wù)后才返回。

一個(gè)_異步_函數(shù)挑格,剛好相反咙冗,會(huì)立即返回,預(yù)定的任務(wù)會(huì)完成但不會(huì)等它完成漂彤。因此雾消,一個(gè)異步函數(shù)不會(huì)阻塞當(dāng)前線程去執(zhí)行下一個(gè)函數(shù)

Deadlock 死鎖

兩個(gè)(有時(shí)更多)東西——在大多數(shù)情況下灾搏,是線程——所謂的死鎖是指它們都卡住了,并等待對(duì)方完成或執(zhí)行其它操作立润。第一個(gè)不能完成是因?yàn)樗诘却诙€(gè)的完成狂窑。但第二個(gè)也不能完成,因?yàn)樗诘却谝粋€(gè)的完成桑腮。

Context Switch 上下文切換

一個(gè)上下文切換指當(dāng)你在單個(gè)進(jìn)程里切換執(zhí)行不同的線程時(shí)存儲(chǔ)與恢復(fù)執(zhí)行狀態(tài)的過(guò)程泉哈。這個(gè)過(guò)程在編寫多任務(wù)應(yīng)用時(shí)很普遍,但會(huì)帶來(lái)一些額外的開(kāi)銷


Concurrency vs Parallelism 并發(fā)與并行

并發(fā)和并行通常被一起提到破讨,所以值得花些時(shí)間解釋它們之間的區(qū)別丛晦。

并發(fā)代碼的不同部分可以“同步”執(zhí)行。然而添忘,該怎樣發(fā)生或是否發(fā)生都取決于系統(tǒng)采呐。多核設(shè)備通過(guò)并行來(lái)同時(shí)執(zhí)行多個(gè)線程;然而搁骑,為了使單核設(shè)備也能實(shí)現(xiàn)這一點(diǎn)斧吐,它們必須先運(yùn)行一個(gè)線程,執(zhí)行一個(gè)上下文切換仲器,然后運(yùn)行另一個(gè)線程或進(jìn)程煤率。這通常發(fā)生地足夠快以致給我們并發(fā)執(zhí)行地錯(cuò)覺(jué)


Queue Types 隊(duì)列類型

首先,系統(tǒng)提供給你一個(gè)叫做?主隊(duì)列(main queue)?的特殊隊(duì)列乏冀。和其它串行隊(duì)列一樣蝶糯,這個(gè)隊(duì)列中的任務(wù)一次只能執(zhí)行一個(gè)。然而辆沦,它能保證所有的任務(wù)都在主線程執(zhí)行昼捍,而主線程是唯一可用于更新 UI 的線程。這個(gè)隊(duì)列就是用于發(fā)生消息給?UIView?或發(fā)送通知的肢扯。

系統(tǒng)同時(shí)提供給你好幾個(gè)并發(fā)隊(duì)列妒茬。它們叫做?全局調(diào)度隊(duì)列(Global Dispatch Queues)?。目前的四個(gè)全局隊(duì)列有著不同的優(yōu)先級(jí):background蔚晨、low乍钻、default?以及?high。要知道铭腕,Apple 的 API 也會(huì)使用這些隊(duì)列银择,所以你添加的任何任務(wù)都不會(huì)是這些隊(duì)列中唯一的任務(wù)。

最后累舷,你也可以創(chuàng)建自己的串行隊(duì)列或并發(fā)隊(duì)列浩考。這就是說(shuō),至少有_五個(gè)_隊(duì)列任你處置:主隊(duì)列被盈、四個(gè)全局調(diào)度隊(duì)列怀挠,再加上任何你自己創(chuàng)建的隊(duì)列析蝴。

以上是調(diào)度隊(duì)列的大框架!

GCD 的“藝術(shù)”歸結(jié)為選擇合適的隊(duì)列來(lái)調(diào)度函數(shù)以提交你的工作绿淋。體驗(yàn)這一點(diǎn)的最好方式是走一遍下邊的列子,我們沿途會(huì)提供一些一般性的建議尝盼。

Thread Safe 線程安全

線程安全的代碼能在多線程或并發(fā)任務(wù)中被安全的調(diào)用吞滞,而不會(huì)導(dǎo)致任何問(wèn)題(數(shù)據(jù)損壞,崩潰盾沫,等)裁赠。線程不安全的代碼在某個(gè)時(shí)刻只能在一個(gè)上下文中運(yùn)行。一個(gè)線程安全代碼的例子是?NSDictionary?赴精。你可以在同一時(shí)間在多個(gè)線程中使用它而不會(huì)有問(wèn)題佩捞。另一方面,NSMutableDictionary?就不是線程安全的蕾哟,應(yīng)該保證一次只能有一個(gè)線程訪問(wèn)它一忱。


?dispatch_sync?:

自定義串行隊(duì)列:在這個(gè)狀況下要非常小心!如果你正運(yùn)行在一個(gè)隊(duì)列并調(diào)用?dispatch_sync?放在同一個(gè)隊(duì)列谭确,那你就百分百地創(chuàng)建了一個(gè)死鎖帘营。

主隊(duì)列(串行):同上面的理由一樣,必須非常小心逐哈!這個(gè)狀況同樣有潛在的導(dǎo)致死鎖的情況芬迄。

并發(fā)隊(duì)列:這才是做同步工作的好選擇,不論是通過(guò)調(diào)度障礙昂秃,或者需要等待一個(gè)任務(wù)完成才能執(zhí)行進(jìn)一步處理的情況禀梳。

?dispatch_async :

自定義串行隊(duì)列:當(dāng)你想串行執(zhí)行后臺(tái)任務(wù)并追蹤它時(shí)就是一個(gè)好選擇。這消除了資源爭(zhēng)用肠骆,因?yàn)槟阒酪淮沃挥幸粋€(gè)任務(wù)在執(zhí)行算途。注意若你需要來(lái)自某個(gè)方法的數(shù)據(jù),你必須內(nèi)聯(lián)另一個(gè) Block 來(lái)找回它或考慮使用?dispatch_sync哗戈。

主隊(duì)列(串行):這是在一個(gè)并發(fā)隊(duì)列上完成任務(wù)后更新 UI 的共同選擇郊艘。要這樣做,你將在一個(gè) Block 內(nèi)部編寫另一個(gè) Block 唯咬。以及纱注,如果你在主隊(duì)列調(diào)用?dispatch_async?到主隊(duì)列,你能確保這個(gè)新任務(wù)將在當(dāng)前方法完成后的某個(gè)時(shí)間執(zhí)行胆胰。

并發(fā)隊(duì)列:這是在后臺(tái)執(zhí)行非 UI 工作的共同選擇狞贱。

dispatch_after?

自定義串行隊(duì)列:在一個(gè)自定義串行隊(duì)列上使用?dispatch_after?要小心。你最好堅(jiān)持使用主隊(duì)列蜀涨。

主隊(duì)列(串行):是使用?dispatch_after?的好選擇瞎嬉;Xcode 提供了一個(gè)不錯(cuò)的自動(dòng)完成模版蝎毡。

并發(fā)隊(duì)列:在并發(fā)隊(duì)列上使用?dispatch_after?也要小心;你會(huì)這樣做就比較罕見(jiàn)氧枣。還是在主隊(duì)列做這些操作吧沐兵。

dispatch_once

以線程安全的方式執(zhí)行且僅執(zhí)行其代碼塊一次。試圖訪問(wèn)臨界區(qū)(即傳遞給?dispatch_once?的代碼)的不同的線程會(huì)在臨界區(qū)已有一個(gè)線程的情況下被阻塞便监,直到臨界區(qū)完成為止

需要記住的是扎谎,這只是讓訪問(wèn)共享實(shí)例線程安全。它絕對(duì)沒(méi)有讓類本身線程安全烧董。類中可能還有其它競(jìng)態(tài)條件毁靶,例如任何操縱內(nèi)部數(shù)據(jù)的情況。這些需要用其它方式來(lái)保證線程安全逊移,例如同步訪問(wèn)數(shù)據(jù)

Dispatch barriers

自定義串行隊(duì)列:一個(gè)很壞的選擇预吆;障礙不會(huì)有任何幫助,因?yàn)椴还茉鯓痈烊粋€(gè)串行隊(duì)列一次都只執(zhí)行一個(gè)操作拐叉。

全局并發(fā)隊(duì)列:要小心;這可能不是最好的主意胶背,因?yàn)槠渌到y(tǒng)可能在使用隊(duì)列而且你不能壟斷它們只為你自己的目的巷嚣。

自定義并發(fā)隊(duì)列:這對(duì)于原子或臨界區(qū)代碼來(lái)說(shuō)是極佳的選擇。任何你在設(shè)置或?qū)嵗男枰€程安全的事物都是使用障礙的最佳候選钳吟。

Dispatch Groups(調(diào)度組)

Dispatch Group 會(huì)在整個(gè)組的任務(wù)都完成時(shí)通知你廷粒。這些任務(wù)可以是同步的,也可以是異步的红且,即便在不同的隊(duì)列也行坝茎。而且在整個(gè)組的任務(wù)都完成時(shí),Dispatch Group 可以用同步的或者異步的方式通知你暇番。因?yàn)橐O(jiān)控的任務(wù)在不同隊(duì)列嗤放,那就用一個(gè)?dispatch_group_t?的實(shí)例來(lái)記下這些不同的任務(wù)。

當(dāng)組中所有的事件都完成時(shí)壁酬,GCD 的 API 提供了兩種通知方式次酌。

第一種是?dispatch_group_wait?,它會(huì)阻塞當(dāng)前線程舆乔,直到組里面所有的任務(wù)都完成或者等到某個(gè)超時(shí)發(fā)生岳服。

dispatch_group_enter?手動(dòng)通知 Dispatch Group 任務(wù)已經(jīng)開(kāi)始。你必須保證?dispatch_group_enter?和?dispatch_group_leave?成對(duì)出現(xiàn)希俩,否則你可能會(huì)遇到詭異的崩潰問(wèn)題

Dispatch Group

自定義串行隊(duì)列:它很適合當(dāng)一組任務(wù)完成時(shí)發(fā)出通知吊宋。

主隊(duì)列(串行):它也很適合這樣的情況。但如果你要同步地等待所有工作地完成颜武,那你就不應(yīng)該使用它璃搜,因?yàn)槟悴荒茏枞骶€程拖吼。然而,異步模型是一個(gè)很有吸引力的能用于在幾個(gè)較長(zhǎng)任務(wù)(例如網(wǎng)絡(luò)調(diào)用)完成后更新 UI 的方式这吻。

并發(fā)隊(duì)列:它也很適合 Dispatch Group 和完成時(shí)通知

dispatch_apply

自定義串行隊(duì)列:串行隊(duì)列會(huì)完全抵消?dispatch_apply?的功能吊档;你還不如直接使用普通的?for?循環(huán)。

主隊(duì)列(串行):與上面一樣橘原,在串行隊(duì)列上不適合使用?dispatch_apply?籍铁。還是用普通的?for?循環(huán)吧。

并發(fā)隊(duì)列:對(duì)于并發(fā)循環(huán)來(lái)說(shuō)是很好選擇趾断,特別是當(dāng)你需要追蹤任務(wù)的進(jìn)度時(shí)。

出處:https://github.com/nixzhu/dev-blog

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末吩愧,一起剝皮案震驚了整個(gè)濱河市芋酌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌雁佳,老刑警劉巖脐帝,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異糖权,居然都是意外死亡堵腹,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門星澳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)疚顷,“玉大人,你說(shuō)我怎么就攤上這事禁偎⊥鹊蹋” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵如暖,是天一觀的道長(zhǎng)笆檀。 經(jīng)常有香客問(wèn)我,道長(zhǎng)盒至,這世上最難降的妖魔是什么酗洒? 我笑而不...
    開(kāi)封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮枷遂,結(jié)果婚禮上樱衷,老公的妹妹穿的比我還像新娘。我一直安慰自己登淘,他們只是感情好箫老,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著黔州,像睡著了一般耍鬓。 火紅的嫁衣襯著肌膚如雪阔籽。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天牲蜀,我揣著相機(jī)與錄音笆制,去河邊找鬼。 笑死涣达,一個(gè)胖子當(dāng)著我的面吹牛在辆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播度苔,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼匆篓,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了寇窑?” 一聲冷哼從身側(cè)響起鸦概,我...
    開(kāi)封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎甩骏,沒(méi)想到半個(gè)月后窗市,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡饮笛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年咨察,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片福青。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡摄狱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出素跺,到底是詐尸還是另有隱情二蓝,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布指厌,位于F島的核電站刊愚,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏踩验。R本人自食惡果不足惜鸥诽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望箕憾。 院中可真熱鬧牡借,春花似錦、人聲如沸袭异。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至碴里,卻和暖如春沈矿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背咬腋。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工羹膳, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人根竿。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓陵像,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親寇壳。 傳聞我的和親對(duì)象是個(gè)殘疾皇子醒颖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 本文首發(fā)于我的個(gè)人博客:「程序員充電站」[https://itcharge.cn]文章鏈接:「?jìng)魉烷T」[https...
    ITCharge閱讀 347,881評(píng)論 308 1,926
  • 目錄 一、基本概念1.多線程2.串行和并行壳炎, 并發(fā)3.隊(duì)列與任務(wù)4.同步與異步5.線程狀態(tài)6.多線程方案 二图贸、GC...
    BohrIsLay閱讀 1,581評(píng)論 5 12
  • 系列文章: 多線程 多線程 pthread、NSThread 多線程 GCD 多線程 NSOperation 多線...
    林安530閱讀 356評(píng)論 0 0
  • 目錄:iOS多線程(一)--pthread冕广、NSThreadiOS多線程(二)--GCD詳解iOS多線程(三)--...
    Claire_wu閱讀 1,075評(píng)論 0 6
  • 例如撒汉,今天我問(wèn)同事,我的這個(gè)顧客約好了時(shí)間嗎涕滋?(內(nèi)心話:沒(méi)有就趕緊約)她說(shuō)她沒(méi)打電話(這是她分內(nèi)工作睬辐,只是我經(jīng)常自...
    Lisa_001閱讀 210評(píng)論 0 0