dispatch_sync 和 dispatch_get_main_queue搭配為什么可能造成死鎖?

上一篇文章 介紹syn/asyn和queue的各種搭配時,提到有產生死鎖崩潰的情況,現簡單介紹下。

例1
- (void)viewDidLoad
{
   NSLog(@"---1");
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"---2");
    });
    NSLog(@"---3");
});

打印了1,并不會打印2和3,會死鎖崩潰,因為dispatch_sync是同步,會阻塞當前主線程,等代碼塊里面內容執行完后再往下繼續執行,然而根據dispatch_get_main_queue判斷,代碼塊內的代碼又需在主線程中執行,主線程已被阻塞了,所以代碼塊處于永遠等待中。

例2
- (void)viewDidLoad {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"----1");
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"----2");
        });
        NSLog(@"---3");
    });
    NSLog(@"---4");
     while (YES) {}
}

2和3永遠不會被打印,因為1在異步子線程中執行,所以可能1比4先打印。
這種情況下,因為2需要在主線程中同步執行,當打印了1后,把異步代碼放到后臺等待獲取主線程,先執行4。然而遇到個死循環阻塞了主線程,而2又需要主線程才能執行,所以2處于永遠等待獲取主線程。

例3
dispatch_queue_t queue = dispatch_get_main_queue();
    NSLog(@"1");
    dispatch_async(queue, ^{
        NSLog(@"2");
        dispatch_sync(queue, ^{
                    NSLog(@"3");
                });
        NSLog(@"4");
    });
     NSLog(@"5");

3和4永遠不會被打印被鎖死,因為
2會在主線程里面打印,然后遇到dispatch_sync,隊列會被阻塞,等待代碼塊3執行完了再往下面執行
而3又需要獲取到主隊列才能執行,然而隊列已被阻塞。
例4
- (void)viewDidLoad {
    NSLog(@"---1");
    dispatch_sync(dispatch_get_global_queue(0, 0), ^{
         NSLog(@"---2");
        dispatch_sync(dispatch_get_global_queue(0,0), ^{
                NSLog(@"---3");
           });
        NSLog(@"---4");
    });
    
     NSLog(@"---5");
}

這里會按照順序打印 1,2,3,4,5,并且都在主線程中打印。
因為2,3都不會開子線程(在當前線程中執行),由于是串行,所以會阻塞當前線程,然而隊列都是global(雖有并發能力,但基于是sync,所以不會開線程),在當前線程(主),串行執行。

例5
- (void)viewDidLoad {
    [super viewDidLoad];
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"---1");
        [self performSelector:@selector(pintLog) withObject:nil afterDelay:2];
        NSLog(@"---3");
    });
}
-(void)pintLog{
    NSLog(@"---2");
}

會打印1,3,永遠不會打印2,因為GCD創建的線程沒有RunLoop,然而performSelector這類方法需要在RunLoop里面執行,所以代碼會失效。

總結:

根據dispatch_async和dispatch_sync判斷是否會阻塞線程。
根據queue判斷是否開線程/還是當前線程執行。

有什么錯誤歡迎批評指正 。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 從哪說起呢? 單純講多線程編程真的不知道從哪下嘴。。 不如我直接引用一個最簡單的問題,以這個作為切入點好了 在ma...
    Mr_Baymax閱讀 2,831評論 1 17
  • 目錄 一、基本概念1.多線程2.串行和并行, 并發3.隊列與任務4.同步與異步5.線程狀態6.多線程方案 二、GC...
    BohrIsLay閱讀 1,612評論 5 12
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,334評論 25 708
  • 原文地址 http://www.cnblogs.com/kenshincui/p/3983982.html 大家都...
    怎樣m閱讀 1,302評論 0 1
  • 假期總是一如既往的過得很快,上大學之后,放假最后一天不再是以前趕作業的匆忙日子,所以時間流逝的更快了。實習的日子里...
    左神話閱讀 2,392評論 19 21