GCD解毒

沒錯就是解毒

前言


GCD做為iOS開發(fā)中多線程管理的重要幫手折砸。起初我只能說是用過看疗,但是并沒有較為仔細的了解它。最近又一次重新梳理了一下睦授,雖然目前來看两芳,還存在一些問題,無法解釋去枷。但還是先做個筆記怖辆,與大家分享下是复。同時,希望大家也能一起探索或者幫忙解答下這些問題:]

<p>

一些概念


首先竖螃,我們來解讀一些基本的概念淑廊。在多線程開發(fā)中我們經(jīng)常會遇到很多的名詞,一時間也沒辦法分清他們到底是什么意思特咆。所以我在這里做個簡單的整理

并行 和 并發(fā)

并發(fā): 統(tǒng)一執(zhí)行很多任務季惩,表面上同時發(fā)生,但是實際上是計算機分時處理的結(jié)果腻格,即CPU在不同的任務之間進行切換蜀备,執(zhí)行一段時間后切換到另一個線程。
并行:真正意義上的同時執(zhí)行任務荒叶。

兩者的區(qū)別實際上用一張圖就能很好的說明

Paste_Image.png

同步 和 異步

同步:等操作完成才返回
異步:直接返回

串行隊列 和 并發(fā)隊列

串行隊列:一次只執(zhí)行一個任務

Paste_Image.png

并發(fā)隊列: 一次執(zhí)行多個任務
Paste_Image.png

這里我們需要說明的是碾阁,無論是并發(fā)隊列還是并行隊列,他們都是FIFO的些楣,也就是說先添加到隊列中的任務會先被執(zhí)行脂凶,但是對于并發(fā)隊列而言,我們不能保證執(zhí)行完成時的順序愁茁。另外蚕钦,在一些博文中會將Concurrent Queue翻譯為 并行隊列,個人認為并不是很嚴謹鹅很。首先是因為Concurrent 本意就是并發(fā)嘶居,并且如果使用并發(fā)這個名詞,對于一些初學者來講可能會產(chǎn)生誤導促煮,隊列中的任務到底是并發(fā)執(zhí)行還是并行執(zhí)行的呢邮屁?

進程 和 線程

進程:是操作系統(tǒng)對于正在運行的程序的一種抽象,在系統(tǒng)上可以同時運行多個進程菠齿,而每個進程都好像在獨立使用硬件
線程:一個進程實際上可以由多個線程的執(zhí)行單元組成佑吝,每個線程都在進程的上下文中,共享同樣的代碼和全局數(shù)據(jù)
進程绳匀、線程和應用程序的關(guān)系:進程為應用程序開辟內(nèi)存空間芋忿,而線程執(zhí)行應用程序代碼
進程和線程的關(guān)系:進程由線程組成、一個進程理論上可以有很多的線程疾棵,但至少有一個主線程戈钢。

死鎖

死鎖: 兩個或多個線程相互等待而導致任何一個線程都不能執(zhí)行。

概念匯總

圖片發(fā)自簡書App

關(guān)于一些問題的想法


我們經(jīng)常會看到以下代碼

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //[self do something];
    });

這段代碼表示我們“開啟一個異步線程是尔,在全局隊列中執(zhí)行”

那么我們?nèi)绻覀儗?code>dispatch_get_global_queue()函數(shù)改為dispatch_get_main_queue()就會說我們在主線程上做處理事務殉了,而事實上我們使用這個函數(shù)創(chuàng)建或得到的是一個隊列而非線程。

更準確的說嗜历,我認為压状,我們使用GCD的時候應該是面向隊列痛阻,而不是線程。在很多的博客中都會使用NSLog(@"current thread is %@", [NSThread currentThread])這段代碼來打印當前的線程,然后告訴你說我們在XX線程上執(zhí)行了代碼抱慌。的確,這樣的方式更加直接的說明了問題蔚携。但是就像我之前提到的房维,開發(fā)者應該面向的是隊列而不是線程,所以這只是輔助說明的一種方式每窖。

OK帮掉,接下來我們討論下dispatch_async和dispatch_sync函數(shù)都干了些什么。開始我以為他們是創(chuàng)建線程用的窒典,就如一些的博文中會講到蟆炊,“每執(zhí)行一次任務的時候,dispatch_async總會為我們開辟一個新的線程”

真的是這樣嗎瀑志?

我在文檔里看到如下說明

dispatch_sync

Submits a block object for execution on a dispatch queue and waits until that block completes.
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_async

Submits a block for asynchronous execution on a dispatch queue and returns immediately.
This function is the fundamental mechanism for submitting blocks to a dispatch queue. Calls to this function always return immediately after the block has been submitted and never wait for the block to be invoked. The target queue determines whether the block is invoked serially or concurrently with respect to other blocks submitted to that same queue. Independent serial queues are processed concurrently with respect to each other.

這里我認為涩搓,這兩個函數(shù)只是用于提交任務或者說block的。他們唯一的區(qū)別是會不會等待任務完成劈猪。對于dispatch_sync而言昧甘,他會提交任務,同時阻塞當前的線程直到任務執(zhí)行完成才會返回战得。 dispatch_async則會在提交任務之后直接返回充边,不阻塞和等待。如此一來常侦,真正和與線程相關(guān)的就可能是隊列了浇冰。

另一種視角


前面提到的在GCD中我們只是面向隊列和任務。隊列包括串行隊列和并發(fā)隊列聋亡,而任務提交是同步或者異步的湖饱。那么我們就來看下這些概念排列組合后的場景。

同步提交 + 串行隊列

Paste_Image.png

說明:在調(diào)用dispatch_sync方法的時候我們指定了添加任務的隊列和任務(block)杀捻。那么該方法就會提交該任務到串行隊列中井厌,然后然后阻塞線程,等待任務完成之后再返回致讥。對于串行隊列仅仆,前面的概念解釋里已經(jīng)說過了,任務一個接一個執(zhí)行垢袱。

異步提交 + 并發(fā)隊列

Paste_Image.png

說明:異步提交的時候墓拜,dispatch_async函數(shù)提交然后直接返回。區(qū)別是并發(fā)隊列會一次執(zhí)行多個任務请契。

同步提交 + 并發(fā)隊列

Paste_Image.png

異步提交 + 串行隊列

Paste_Image.png

代碼部分

我們在從代碼部分去理解同步和異步的問題


圖片發(fā)自簡書App

左側(cè)兩段輸出咳榜,我們可以看到夏醉,都是同步提交,無論是提交到串行隊列還是并發(fā)隊列涌韩,執(zhí)行的順序都是一樣的畔柔。并且提交任務前后的代碼的順序都是依次執(zhí)行的。

在看右側(cè)部分臣樱,由于異步提交后直接返回不等待執(zhí)行完成靶擦。所以任務提交前后的代碼會先于任務中的代碼執(zhí)行。

接下來雇毫,我們在從代碼的角度去理解串行隊列和并發(fā)隊列

并發(fā)

圖片發(fā)自簡書App

在同樣是異步的前提下玄捕,任務前后的代碼都先于任務執(zhí)行了(當然這并不是絕對的)。我們看到在串行隊列中棚放,執(zhí)行任務的線程不在主線程中枚粘,但是他們都是在一個線程中去處理。也正因為任務前后的代碼執(zhí)行和任務代碼執(zhí)行的線程不同飘蚯,所以我們并不能保證任務部分的代碼和任務后的代碼的執(zhí)行先后性赌结。因此會出現(xiàn)任務代碼先執(zhí)行,在執(zhí)行過程又出現(xiàn)任務后的打印輸出孝冒。

圖片發(fā)自簡書App

同樣是同步提交的情況下柬姚,兩個輸出完全一致。串行隊列同步提交的情況我們可以理解庄涡,因為它一次只執(zhí)行一個任務量承,所以線程號是一樣的。但是穴店,并發(fā)隊列的情況下撕捍,該怎么理解?其實也很簡單泣洞,因為他是同步提交忧风,需要等到當前任務完成后返回再進行后續(xù)的操作,所以即使是并發(fā)的隊列球凰,我們看到的效果還是和串行一樣狮腿。

遺留的問題

首先很感謝你能看到這里,聽我瞎扯那么多呕诉。
以上是我個人的理解缘厢,感覺與一些博文中的思想有些出入,所有我也不是很確定甩挫。我僅以
我看到的為參考贴硫,并提出自己的理解。

目前還有以下問題暫時沒有想通:

1)隊列和線程的關(guān)系

從文檔中有看到系統(tǒng)實際上有維持一個線程池伊者,但是沒有說清隊列和它有什么具體的關(guān)系英遭。

2)隊列和主線程的關(guān)系

如下圖间护,同樣是在主線程中執(zhí)行,但是如果將這個queue改成main queue時就會報錯挖诸。

圖片發(fā)自簡書App

歸根結(jié)底還是沒有理清線程和隊列的關(guān)系汁尺,或者說是主線,隊列税灌,其它線程這三者的關(guān)系均函。

如果覺得我的想法有問題的同學亿虽,請幫忙指正菱涤,萬分感謝。
如果覺得我理解有道理的同學洛勉,希望能一起探討一下遺留的問題粘秆,共同完善知識體系:]

最后放上源代碼
GCD解毒Demo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市收毫,隨后出現(xiàn)的幾起案子攻走,更是在濱河造成了極大的恐慌,老刑警劉巖此再,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件昔搂,死亡現(xiàn)場離奇詭異,居然都是意外死亡输拇,警方通過查閱死者的電腦和手機摘符,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來策吠,“玉大人逛裤,你說我怎么就攤上這事『锬ǎ” “怎么了带族?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蟀给。 經(jīng)常有香客問我蝙砌,道長,這世上最難降的妖魔是什么跋理? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任拍霜,我火速辦了婚禮,結(jié)果婚禮上薪介,老公的妹妹穿的比我還像新娘祠饺。我一直安慰自己,他們只是感情好汁政,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布道偷。 她就那樣靜靜地躺著缀旁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪勺鸦。 梳的紋絲不亂的頭發(fā)上并巍,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音换途,去河邊找鬼懊渡。 笑死,一個胖子當著我的面吹牛军拟,可吹牛的內(nèi)容都是我干的剃执。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼懈息,長吁一口氣:“原來是場噩夢啊……” “哼肾档!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起辫继,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤怒见,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后姑宽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體遣耍,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年炮车,在試婚紗的時候發(fā)現(xiàn)自己被綠了舵变。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡示血,死狀恐怖棋傍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情难审,我是刑警寧澤瘫拣,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站告喊,受9級特大地震影響麸拄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜黔姜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一拢切、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧秆吵,春花似錦淮椰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽泻拦。三九已至,卻和暖如春忽媒,著一層夾襖步出監(jiān)牢的瞬間争拐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工晦雨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留架曹,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓闹瞧,卻偏偏與公主長得像绑雄,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子夹抗,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

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

  • GCD筆記 總結(jié)一下多線程部分,最強大的無疑是GCD,那么先從這一塊部分講起. Dispatch Queue的種類...
    jins_1990閱讀 761評論 0 1
  • 從哪說起呢绳慎? 單純講多線程編程真的不知道從哪下嘴纵竖。漠烧。 不如我直接引用一個最簡單的問題,以這個作為切入點好了 在ma...
    Mr_Baymax閱讀 2,757評論 1 17
  • GCD GCD簡介 Grand Central Dispatch中樞調(diào)度器 純C語言的靡砌,提供了非常強大的函數(shù) 優(yōu)勢...
    彼岸的黑色曼陀羅閱讀 439評論 0 0
  • iOS中GCD的使用小結(jié) 作者dullgrass 2015.11.20 09:41*字數(shù) 4996閱讀 20199...
    DanDanC閱讀 829評論 0 0
  • 一已脓,奇跡 1,今天我很開心?一切都很順利!諸事順順當當?shù)耐ㄑ辏≈x謝我的天使真我指導靈給我完美生活度液! 2,今天我很開心?...
    張秀琦閱讀 226評論 0 0