GCD死鎖詳解

在iOS開(kāi)發(fā)中,當(dāng)遇到網(wǎng)絡(luò)請(qǐng)求和耗時(shí)操作通常需要另外開(kāi)一個(gè)子線程灰伟,然后需要刷新UI的時(shí)候回到主線程刷新宪塔;這里就要用到多線程的技術(shù)第献,iOS多線程通常有四種方式:PThread,NSThread,NSOperation,GCD;在這里主要介紹一下GCD的情況下死鎖的幾種情況,以及簡(jiǎn)單的分析:
注:很多資料來(lái)自前輩的文章俱恶。
1雹嗦、進(jìn)程和線程的概念:
正在進(jìn)行中的程序被稱為進(jìn)程,負(fù)責(zé)程序運(yùn)行的內(nèi)存分配合是,每一個(gè)進(jìn)程都有自己獨(dú)立的虛擬內(nèi)存空間了罪。
線程是進(jìn)程中一個(gè)獨(dú)立的執(zhí)行路徑,即主線程聪全,主線程有1M的棧區(qū)泊藕,對(duì)于耗時(shí)的執(zhí)行路徑,可以放在子線程(512K棧區(qū))中執(zhí)行荔烧。
新建線程會(huì)消耗內(nèi)存空間和CPU事件吱七,線程太多會(huì)降低系統(tǒng)的運(yùn)行性能,多線程是通過(guò)CPU時(shí)分復(fù)用實(shí)現(xiàn)的鹤竭。
多線程是為了并發(fā)執(zhí)行多項(xiàng)任務(wù)踊餐,不會(huì)提高單個(gè)算法本身的執(zhí)行效率。
2臀稚、同步和異步
同步就是順序執(zhí)行吝岭,執(zhí)行完一個(gè)再執(zhí)行下一個(gè),需要等待吧寺、協(xié)調(diào)運(yùn)行窜管。異步就是彼此獨(dú)立,在等待某事件的過(guò)程中繼續(xù)做自己的事,不需要等待這一事件完成后再工作稚机。線程就是實(shí)現(xiàn)異步的一個(gè)方式幕帆。異步是讓調(diào)用方法的主線程不需要同步等待另一線程的完成,從而可以讓主線程干其它的事情赖条。
異步和多線程并不是一個(gè)同等關(guān)系,異步是最終目的,多線程只是我們實(shí)現(xiàn)異步的一種手段失乾。異步是當(dāng)一個(gè)調(diào)用請(qǐng)求發(fā)送給被調(diào)用者,而調(diào)用者不用等待其結(jié)果的返回而可以做其它的事情。實(shí)現(xiàn)異步可以采用多線程技術(shù)或則交給另外的進(jìn)程來(lái)處理纬乍。
3碱茁、串行和并行
你可以創(chuàng)建任意個(gè)數(shù)的串行隊(duì)列,每個(gè)隊(duì)列依次執(zhí)行添加的任務(wù)仿贬,一個(gè)隊(duì)列同一時(shí)刻只能執(zhí)行一個(gè)任務(wù)(串行)纽竣,但是各個(gè)隊(duì)列之間不影響,可以并發(fā)執(zhí)行。每個(gè)隊(duì)列中的任務(wù)運(yùn)行在一個(gè)由各自串行隊(duì)列維護(hù)的獨(dú)立線程上蜓氨,一個(gè)隊(duì)列中只有一個(gè)線程聋袋。
并行隊(duì)列是不允許自己創(chuàng)建的,系統(tǒng)中存在三個(gè)不同優(yōu)先級(jí)的并行隊(duì)列语盈。并行隊(duì)列依舊按照任務(wù)添加的順序啟動(dòng)任務(wù)舱馅,但是,后一個(gè)任務(wù)無(wú)須等待前一個(gè)任務(wù)執(zhí)行完畢刀荒,而是啟動(dòng)第一個(gè)任務(wù)后代嗤,立即啟動(dòng)下一個(gè)任務(wù)。至于同一時(shí)刻允許同時(shí)運(yùn)行多少個(gè)任務(wù)有系統(tǒng)決定缠借。任務(wù)各自運(yùn)行在并行隊(duì)列為他們提供的獨(dú)立線程上干毅,并行隊(duì)列中同時(shí)運(yùn)行多少個(gè)任務(wù),就必須維護(hù)多少個(gè)線程泼返。

上面講解了關(guān)于GCD的一些基本的概念硝逢,接著我們舉幾個(gè)GCD死鎖的案例:
案例一:當(dāng)同步遇到了串行

    NSLog(@"1");//任務(wù)1
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"2");//任務(wù)2
    });
    NSLog(@"3");//任務(wù)3

控制臺(tái)輸出結(jié)果:

2017-02-23 10:21:00.858 GCDTest[1462:51203] 1

分析:
dispatch_sync是一個(gè)同步線程;
dispatch_get_main_queue()表示運(yùn)行在主線程中的主隊(duì)列绅喉;
任務(wù)二是同步線程的任務(wù)渠鸽。
任務(wù)三需要等待任務(wù)二結(jié)束之后再執(zhí)行。
分析:首先會(huì)執(zhí)行任務(wù)1毫無(wú)疑問(wèn)柴罐,然后程序遇到了同步線程徽缚,任務(wù)三要等待同步線程執(zhí)行完再執(zhí)行,而主線程是一個(gè)特殊的串行對(duì)了革屠。遵循FIFO原則來(lái)執(zhí)行任務(wù)凿试,然后任務(wù)二被加在任務(wù)三的后面要等待任務(wù)三完成才執(zhí)行,這樣就進(jìn)入了互相等待的局面似芝。

案例二:當(dāng)同步遇到了并行

    NSLog(@"1");//任務(wù)1
    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        NSLog(@"2");//任務(wù)2
    });
    NSLog(@"3");//任務(wù)3

控制臺(tái)輸出結(jié)果:

2017-02-23 10:31:51.647 GCDTest[1488:56267] 1
2017-02-23 10:31:51.648 GCDTest[1488:56267] 2
2017-02-23 10:31:51.648 GCDTest[1488:56267] 3

分析:
毫無(wú)疑問(wèn)首先執(zhí)行任務(wù)一那婉,然后遇到了同步線程,任務(wù)三要等待同步線程執(zhí)行完再執(zhí)行党瓮,然后任務(wù)二被加在了子線程详炬,在子線程執(zhí)行完任務(wù)二然后回到主線程繼續(xù)執(zhí)行任務(wù)三。

案例三:同步異步都有

    dispatch_queue_t queue = dispatch_queue_create("com.GCD.serial", DISPATCH_QUEUE_SERIAL);
    NSLog(@"1");//任務(wù)1
    dispatch_async(queue, ^{
        NSLog(@"2");//任務(wù)2
        dispatch_sync(queue, ^{
            NSLog(@"3");//任務(wù)3
        });
        NSLog(@"4");//任務(wù)4
    });
    NSLog(@"5");//任務(wù)5

控制臺(tái)輸出結(jié)果:

2017-02-23 10:47:23.876 GCDTest[1510:63863] 1
2017-02-23 10:47:23.877 GCDTest[1510:63863] 5
2017-02-23 10:47:23.877 GCDTest[1510:63901] 2
//2和5的輸出順序不一定寞奸,3痕寓,4沒(méi)有輸出

分析:
首先,執(zhí)行任務(wù)一蝇闭,毫無(wú)疑問(wèn),然后遇到異步線程操作硬毕,任務(wù)5不必等一步線程操作完再執(zhí)行呻引,所以任務(wù)2和任務(wù)5執(zhí)行先后不一定,二異步操作dispatch_async(queue, ^{})中是串行隊(duì)列操作DISPATCH_QUEUE_SERIAL吐咳,任務(wù)二和任務(wù)四與任務(wù)三依次執(zhí)行逻悠,而任務(wù)三在同步隊(duì)列中元践,任務(wù)四又要等任務(wù)三執(zhí)行完再執(zhí)行,這樣就造成了任務(wù)三和任務(wù)四互相等待的結(jié)局童谒,死鎖单旁。

案例四:異步遇到同步回主線程

    NSLog(@"1");//任務(wù)1
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"2");//任務(wù)2
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"3");//任務(wù)3
        });
        NSLog(@"4");//任務(wù)4
    });
    NSLog(@"5");//任務(wù)5

控制臺(tái)輸出結(jié)果:

2017-02-23 11:08:01.142 GCDTest[1562:72662] 1
2017-02-23 11:08:01.143 GCDTest[1562:72662] 5
2017-02-23 11:08:01.143 GCDTest[1562:72712] 2
2017-02-23 11:08:01.149 GCDTest[1562:72662] 3
2017-02-23 11:08:01.149 GCDTest[1562:72712] 4

分析:
顯然,首先執(zhí)行任務(wù)1饥伊,然后遇到異步全局隊(duì)列象浑,所以異步隊(duì)列和任務(wù)5同時(shí)執(zhí)行,不分先后琅豆,然后異步隊(duì)列中先執(zhí)行任務(wù)2愉豺,遇到同步主隊(duì)列,任務(wù)4要等任務(wù)3完成之后執(zhí)行茫因,而任務(wù)3和任務(wù)4四不在一個(gè)隊(duì)列里蚪拦,所以任務(wù)3不必等待任務(wù)4的完成。所以冻押,整個(gè)案例的執(zhí)行結(jié)果是:15234或者12534驰贷。

案例5:主線程上出現(xiàn)無(wú)限循環(huán):

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"1");//任務(wù)1
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"2");//任務(wù)2
        });
        NSLog(@"3");//任務(wù)3
    });
    NSLog(@"4");//任務(wù)4
    while (1) {
        
    }
    NSLog(@"5");//任務(wù)5

控制臺(tái)輸出結(jié)果:

2017-02-23 11:23:36.925 GCDTest[1584:78484] 1
2017-02-23 11:23:36.925 GCDTest[1584:78447] 4
//或者1 4

分析:
首先是異步線程,任務(wù)4不用等待任務(wù)1的執(zhí)行洛巢,同時(shí)執(zhí)行括袒,所以任務(wù)1和任務(wù)4肯定能執(zhí)行到,順序不一定狼渊,然后任務(wù)4之后遇到死循環(huán)不再往下執(zhí)行任務(wù)5箱熬,而異步隊(duì)列中任務(wù)2又被加入了串行主隊(duì)列任務(wù)5的后面,所以任務(wù)2也不會(huì)執(zhí)行狈邑,而任務(wù)1在之前之后遇到同步操作城须,任務(wù)3要等待任務(wù)2結(jié)束后再執(zhí)行,所以任務(wù)3也不會(huì)執(zhí)行米苹,因此最后結(jié)果是1 4或者4 1糕伐。

總結(jié):暫時(shí)能找到的死鎖的情況主要就這幾種,如果文章中有不準(zhǔn)確的地方還望指正蘸嘶,或者有可以補(bǔ)充的地方也希望提出來(lái)良瞧,本人小白一枚,互相學(xué)習(xí)训唱。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末褥蚯,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子况增,更是在濱河造成了極大的恐慌赞庶,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異歧强,居然都是意外死亡澜薄,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門摊册,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)肤京,“玉大人,你說(shuō)我怎么就攤上這事茅特⊥郑” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵温治,是天一觀的道長(zhǎng)饭庞。 經(jīng)常有香客問(wèn)我,道長(zhǎng)熬荆,這世上最難降的妖魔是什么舟山? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮卤恳,結(jié)果婚禮上累盗,老公的妹妹穿的比我還像新娘。我一直安慰自己突琳,他們只是感情好若债,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著拆融,像睡著了一般蠢琳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上镜豹,一...
    開(kāi)封第一講書(shū)人閱讀 52,475評(píng)論 1 312
  • 那天傲须,我揣著相機(jī)與錄音,去河邊找鬼趟脂。 笑死泰讽,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的昔期。 我是一名探鬼主播已卸,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼硼一!你這毒婦竟也來(lái)了累澡?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤般贼,失蹤者是張志新(化名)和其女友劉穎永乌,沒(méi)想到半個(gè)月后惑申,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡翅雏,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了人芽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片望几。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖萤厅,靈堂內(nèi)的尸體忽然破棺而出橄抹,到底是詐尸還是另有隱情,我是刑警寧澤惕味,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布楼誓,位于F島的核電站,受9級(jí)特大地震影響名挥,放射性物質(zhì)發(fā)生泄漏疟羹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一禀倔、第九天 我趴在偏房一處隱蔽的房頂上張望榄融。 院中可真熱鬧,春花似錦救湖、人聲如沸愧杯。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)力九。三九已至,卻和暖如春邑闺,著一層夾襖步出監(jiān)牢的瞬間跌前,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工检吆, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留舒萎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓蹭沛,卻偏偏與公主長(zhǎng)得像臂寝,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子摊灭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361

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