GCD避免死鎖的三要素

平時總在用GCD,但你知不知道,GCD一不小心就會出現(xiàn)死鎖,如果死鎖在主線程上,整個程序就完了,所以避免死鎖是我們則無旁貸的責任忍些。

那我們先看看造成GCD死鎖的三要素(以下內(nèi)容是我個人總結(jié),并寫了一些測試用例,如有不對的地方,請大家指正 PS:我把GCD死鎖分成 “普通死鎖” ,“高級死鎖”,"混合死鎖")

普通死鎖 必要條件

1.隊列 串行隊列:1 并行隊列:0
2.調(diào)度方法 同步調(diào)用(dispatch_sync):1 異步調(diào)用(dispatch_async):0
3.同一個Q 當前所分發(fā)到的Q 和 "外部Q" 是否是同一個Q 同一個:1 不同:0

PS:"外部Q"是指
1.當前嵌套在外部的Q 如以下形式,Q1就是外部Q

dispatch_sync(Q1, ^{
     NSLog(@"b");
     dispatch_sync(Q2, ^{
            NSLog(@"c");
     });
  });)              

2.外部的方法執(zhí)行時 所在的Q 如以下形式 dead1第二次運行時所在的Q是Q1 它就是外部Q

- (void)dead1{
    NSLog(@"不死1");
     __weak typeof (self) weakSelf = self;
     dispatch_sync(Q1, ^{
           NSLog(@"第二次運行死");
           [weakSelf dead1];
});}

#######結(jié)論: 如果三個條件同時滿足 則死鎖,如果其中一個不滿足 不會死鎖

高級死鎖 必要條件

1.調(diào)度方法 同步阻塞調(diào)用(dispatch_barrier_sync):1 異步阻塞調(diào)用(dispatch_barrier_async):0
2.同一個Q 當前所分發(fā)到的Q 和 "外部Q" 是否是同一個Q 同一個:1 不同:0

#######結(jié)論: 如果兩個條件同時滿足 則死鎖,如果其中一個不滿足 不會死鎖 (高級死鎖主要針對dispatch_barrier而言)

混合死鎖 必要條件

1.調(diào)度方法 同步阻塞調(diào)用(dispatch_barrier_sync)或同步調(diào)用(dispatch_sync):1 異步阻塞調(diào)用(dispatch_barrier_async)或異步調(diào)用(dispatch_async):0
2.同一個Q 當前所分發(fā)到的Q 和 "外部Q" 是否是同一個Q 同一個:1 不同:0

#######結(jié)論: 如果兩個條件同時滿足 則死鎖,如果其中一個不滿足 不會死鎖 (混合死鎖主要針對dispatch_barrier 和 dispatch_async,dispatch_sync嵌套調(diào)用而言)


以下是死鎖測試用例

- (void)viewDidLoad 
{
     [super viewDidLoad];
    // 創(chuàng)建兩個串行隊列和一個并行隊列
    _serialQueue = dispatch_queue_create("aabbcc", DISPATCH_QUEUE_SERIAL);
    _secondSerialQueue = dispatch_queue_create("ssss", DISPATCH_QUEUE_SERIAL);
    _concurrentQueue = dispatch_queue_create("dddd", DISPATCH_QUEUE_CONCURRENT); 
    [self dead1];
    [self dead2];
    [self dead3];
 }

一 普通死鎖

- (void)dead1
{
    NSLog(@"不死1");
    __weak typeof (self) weakSelf = self;
    dispatch_sync(_serialQueue, ^{
        NSLog(@"第二次運行死");
        [weakSelf dead1];
    });
} 

PS:打印日志如下:
2015-10-29 16:46:35.611 DeadLockTest[19971:204243] 不死1
2015-10-29 16:46:35.612 DeadLockTest[19971:204243] 第二次運行死
2015-10-29 16:46:35.612 DeadLockTest[19971:204243] 不死1
原因 在[weakSelf dead1]; 循環(huán)調(diào)用方法本身時,它就在_serialQueue隊列上運行,此時“dispatch_sync(_serialQueue, ^{}” 滿足條件三,同一個Q _serialQueue上 同時又滿足 串行Q 和 同步分發(fā) 所以在第二次運行時產(chǎn)生死鎖。

- (void)dead2
{
    NSLog(@"不死1");
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"死鎖");
    });
}    

PS:打印日志如下:
2015-10-29 16:52:45.435 DeadLockTest[20036:206574] 不死1
原因 dispatch_get_main_queue() 是主Q dead2本身就在主Q 上運行 符合同一個Q 并且同時符合2,3條件 所以死鎖

二 高級死鎖

//死在子線程
- (void)dead3
{
    //并行隊列死鎖
    NSLog(@"a");
    dispatch_async(_concurrentQueue, ^{
        NSLog(@"b");
        dispatch_barrier_sync(_concurrentQueue, ^{
             NSLog(@"c");
        });
    });
}

PS:打印日志如下:
2015-10-29 18:15:02.522 DeadLockTest[27790:256689] a
2015-10-29 18:15:05.919 DeadLockTest[27790:256851] b
原因 同時滿足 1都是同一個Q _concurrentQueue 2同步分發(fā) 使用dispatch_barrier_sync 所以死鎖

三 混合死鎖

//混合模式,內(nèi)部使用dispatch_sync 又是同一Q _concurrentQueue 死鎖
- (void)dead4
{
    NSLog(@"不死1");
    dispatch_barrier_async(_concurrentQueue, ^{
        NSLog(@"不死2");
       dispatch_sync(_concurrentQueue, ^{
           NSLog(@"死在子線程上");
       });
    });
}

PS:打印日志如下:
2015-10-30 10:13:08.544 DeadLockTest[5346:35961] 不死1
2015-10-30 10:13:08.550 DeadLockTest[5346:36036] 不死2
原因 同時滿足 1都是同一個Q _concurrentQueue 2同步分發(fā) 使用dispatch_sync 所以死鎖

//混合模式,內(nèi)部使用dispatch_barrier_sync 又是同一Q _concurrentQueue 死鎖
- (void)dead5
{
    NSLog(@"不死1");
    dispatch_async(_concurrentQueue, ^{
        NSLog(@"不死2");
        dispatch_barrier_sync(_concurrentQueue, ^{
           NSLog(@"死在子線程上");
       });
    });
}

PS:打印日志如下:
2015-10-30 10:14:08.544 DeadLockTest[5346:35961] 不死1
2015-10-30 10:14:08.550 DeadLockTest[5346:36036] 不死2
原因 同時滿足 1都是同一個Q _concurrentQueue 2同步分發(fā) 使用dispatch_barrier_sync 所以死鎖


以下是非死鎖測試用例

/*打破條件1  _concurrentQueue 是并行隊列 不死鎖 */
- (void)noDead1
{
    NSLog(@"a");
    dispatch_async(_concurrentQueue, ^{
        NSLog(@"b");
       dispatch_sync(_concurrentQueue, ^{
           NSLog(@"c");
       });
    });
}

PS:打印日志如下
2015-10-29 18:22:36.724 DeadLockTest[27922:261502] a
2015-10-29 18:22:36.725 DeadLockTest[27922:261633] b
2015-10-29 18:22:36.726 DeadLockTest[27922:261633] c

  /*雖然說三條日志都在主線程上執(zhí)行,但是因為是在兩個不同的隊列上 打破條件3  
  不會死鎖 _serialQueue和_secondSerialQueue 不是同一個隊列*/
- (void)noDead2
{
    NSLog(@"不死1");
    dispatch_sync(_serialQueue, ^{
        NSLog(@"不死2");
        dispatch_sync(_secondSerialQueue, ^{
            NSLog(@"不死3");
        });
    });
}

PS:打印日志如下
2015-10-29 18:26:23.876 DeadLockTest[27977:263046] 不死1
2015-10-29 18:26:23.877 DeadLockTest[27977:263046] 不死2
2015-10-29 18:26:23.878 DeadLockTest[27977:263046] 不死3


以上就是對死鎖的分析,如果掌握了這幾個必要條件,趕快用下面的鏈接練練手吧,檢驗一下對不對
http://www.cnblogs.com/tangbinblog/p/4133481.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末仰楚,一起剝皮案震驚了整個濱河市沃粗,隨后出現(xiàn)的幾起案子挂绰,更是在濱河造成了極大的恐慌抛腕,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肝劲,死亡現(xiàn)場離奇詭異迁客,居然都是意外死亡,警方通過查閱死者的電腦和手機辞槐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門掷漱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人榄檬,你說我怎么就攤上這事切威。” “怎么了丙号?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵先朦,是天一觀的道長。 經(jīng)常有香客問我犬缨,道長喳魏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任怀薛,我火速辦了婚禮刺彩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘枝恋。我一直安慰自己创倔,他們只是感情好,可當我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布焚碌。 她就那樣靜靜地躺著畦攘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪十电。 梳的紋絲不亂的頭發(fā)上知押,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天,我揣著相機與錄音鹃骂,去河邊找鬼台盯。 笑死,一個胖子當著我的面吹牛畏线,可吹牛的內(nèi)容都是我干的静盅。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼寝殴,長吁一口氣:“原來是場噩夢啊……” “哼蒿叠!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起杯矩,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤栈虚,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后史隆,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體魂务,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年泌射,在試婚紗的時候發(fā)現(xiàn)自己被綠了粘姜。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡熔酷,死狀恐怖孤紧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拒秘,我是刑警寧澤号显,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布臭猜,位于F島的核電站,受9級特大地震影響押蚤,放射性物質(zhì)發(fā)生泄漏蔑歌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一揽碘、第九天 我趴在偏房一處隱蔽的房頂上張望次屠。 院中可真熱鬧,春花似錦雳刺、人聲如沸劫灶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽本昏。三九已至,卻和暖如春滞详,著一層夾襖步出監(jiān)牢的瞬間凛俱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工料饥, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蒲犬,地道東北人。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓岸啡,卻偏偏與公主長得像原叮,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子巡蘸,可洞房花燭夜當晚...
    茶點故事閱讀 45,691評論 2 361

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