dispatch_sync()死鎖問題個人疑問

源碼塊一:
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    NSLog(@"%@",[NSThread currentThread]);  
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"Hello World");
    });
}

分析:

  • 當前dispatch_sync()函數在主線程中調用,可以用 NSLog(@"%@",[NSThread currentThread]); 驗證
  • 調用dispatch_sync()函數會立即阻塞調用時該函數所在的線程,即主線程等待dispatch_sync()函數返回
  • dispatch_sync()函數追加任務(即Block代碼塊)到主隊列dispatch_get_main_queue()中,主隊列是一種特殊的串行隊列
  • 主隊列的任務在主線程中執行,但此時主線程被阻塞,無法執行Block代碼塊,導致dispatch_sync()函數無法返回,一直等待Block被主線程執行
  • 最終導致死鎖
源碼塊二:
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    NSLog(@"1-----%@",[NSThread currentThread]);
    
    //創建一個串行隊列
    dispatch_queue_t queue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);
    
    //異步函數產生一個新的線程
    dispatch_async(queue, ^{
        NSLog(@"2-----%@",[NSThread currentThread]);
        
       //向新線程中用同步函數dispatch_sync()追加任務
        dispatch_sync(queue, ^{
            NSLog(@"3-----%@",[NSThread currentThread]);
        });
    });   
}

控制臺:
1-----<NSThread: 0x7ff8aad00220>{number = 1, name = main}
2-----<NSThread: 0x7ff8aad11670>{number = 2, name = (null)}

分析:

  • 在產生的新的線程(number = 2 , name = (null))中,調用函數dispatch_sync(),立即阻塞當前線程,即新開的線程,此時線程阻塞,等待dispatch_sync()函數返回.
  • 使用 dispatch_sync() 追加任務NSLog(@"3-----%@",[NSThread currentThread]);到隊列queue中, 但是當前線程被阻塞,無法執行Block代碼塊,Block代碼塊等待被線程執行.
  • 最終導致死鎖.
源碼塊三:
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    NSLog(@"1-----%@",[NSThread currentThread]);
    
    //創建一個串行隊列
    dispatch_queue_t queue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);
    
    //異步函數產生一個新的線程
    dispatch_async(queue, ^{
        NSLog(@"2-----%@",[NSThread currentThread]);
        
        //創建一個新的串行隊列
        dispatch_queue_t queue2 = dispatch_queue_create("newQueue", DISPATCH_QUEUE_SERIAL);
       
        //在新線程中用同步函數dispatch_sync()向新建的串行隊列中追加任務
        dispatch_sync(queue2, ^{
            NSLog(@"3-----%@",[NSThread currentThread]);
        });
    });
    
}

控制臺:
1-----<NSThread: 0x7fe5daf01730>{number = 1, name = main}
2-----<NSThread: 0x7fe5dac448f0>{number = 2, name = (null)}
3-----<NSThread: 0x7fe5dac448f0>{number = 2, name = (null)}

可以看到該代碼塊并沒有產生死鎖,但是queue2隊列也是在新線程中,為什么調用dispatch_sync()函數時,并沒有阻塞<NSThread: 0x7fe5dac448f0>{number = 2, name = (null)}這條線程,從而使得dispatch_sync()中的任務在新線程中被執行.

那么我的問題就是: 用異步函數創建新線程時所用到的隊列,即代碼中的queue

dispatch_async(queue, ^{
        NSLog(@"2-----%@",[NSThread currentThread]);

如果為串行隊列(并發隊列并不會有該情況),那么該隊列 是否可以認為是 該新線程中的 "主隊列",類似于源碼塊一的效果.

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

推薦閱讀更多精彩內容

  • NSThread 第一種:通過NSThread的對象方法 NSThread *thread = [[NSThrea...
    攻城獅GG閱讀 830評論 0 3
  • 從哪說起呢? 單純講多線程編程真的不知道從哪下嘴。。 不如我直接引用一個最簡單的問題,以這個作為切入點好了 在ma...
    Mr_Baymax閱讀 2,818評論 1 17
  • 在這篇文章中,我將為你整理一下 iOS 開發中幾種多線程方案,以及其使用方法和注意事項。當然也會給出幾種多線程的案...
    張戰威ican閱讀 612評論 0 0
  • 1.Pthreads 真正跨平臺的多線程技術,可以跨UNIX、Linux、windows平臺。 創建Pthread...
    Ljson閱讀 3,154評論 3 29
  • 明天就要去面試了,本來是想找份兼職做做的,但感覺明天的面試是一定能過的,想我這么機智的少年。哈哈哈哈。 我的原意...
    一只貓的特立獨行閱讀 202評論 0 0