2015-07-20 46 views
1

我在viewDidLoadGCD僵局OS X,但不能在iOS

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0); 
    NSLog(@"First"); 
    dispatch_async(queue, ^{ 
     NSLog(@"Third"); 
     dispatch_sync(queue, ^{ 
      NSLog(@"Fourth"); 
     }); 
     NSLog(@"Last"); 
    }); 
    NSLog(@"Second"); 
} 

打印出這個代碼:

2015-07-20 19:12:54.325 Test[7574:431705] First 
2015-07-20 19:12:54.326 Test[7574:431736] Third 
2015-07-20 19:12:54.326 Test[7574:431736] Fourth 
2015-07-20 19:12:54.326 Test[7574:431705] Second 
2015-07-20 19:12:54.326 Test[7574:431736] Last 

這也不同於一些處決。有時它會打印出「第一,第二,第三,第四,最後」以及其他時間它會產生上面的輸出。

另外,我有一個test.m文件有以下幾點: 的#include

int main() { 
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0); 
    NSLog(@"First"); 
    dispatch_async(queue, ^{ 
     NSLog(@"Third"); 
     dispatch_sync(queue, ^{ 
      NSLog(@"Fourth"); 
     }); 
     NSLog(@"Last"); 
    }); 
    NSLog(@"Second"); 
    return 0; 
} 

並且這產生:

2015-07-20 19:12:36.067 tester[7568:431388] First 
2015-07-20 19:12:36.068 tester[7568:431388] Second 

我不明白,爲什麼在iOS模擬器它打印出所有在Mac上它會打印「First」和「Second」,然後出現死鎖。我預計iOS代碼也會出現死鎖,但會打印出「Third」和「Fourth」。沒有任何其他處理iOS代碼中的線程。此外,當NSLog(@"First")被註釋掉,對test.m一些執行它產生不同的東西,如下圖所示:

$: ./tester 
2015-07-20 19:19:31.030 tester[7608:433729] Second 
$: ./tester 
2015-07-20 19:19:32.268 tester[7609:433738] Third 
2015-07-20 19:19:32.268 tester[7609:433737] Second 
$ ./tester 
2015-07-20 19:19:32.620 tester[7610:433740] Second 
$: ./tester 
2015-07-20 19:19:33.812 tester[7611:433744] Third 
2015-07-20 19:19:33.812 tester[7611:433743] Second 

我不知道是什麼原因造成的輸出差異。這是iOS處理與OS X不同的線程的方式嗎?如果有人能解釋發生了什麼,我將不勝感激

+3

它似乎沒有死鎖。在後臺線程有機會運行或完成之前,似乎'main'只是返回(並且應用程序終止)。 – rmaddy

+0

我第二@ rmaddy的建議。你可以使用'dispatch_group'來確保你在等待後臺任務完成,或者作爲一個簡單的測試,只是睡主線程? –

+0

啊沒有想到這一點,但睡在最後的主線後,它似乎經歷了所有這一切。在主線程休眠之後,日誌中的不一致似乎也消失了。我認爲'dispatch_async'立即返回,所以'Second'將永遠打印,無論什麼 – somtingwong

回答

2

在Mac上,您沒有死鎖。這是一個簡單的情況,main完成,應用程序在後臺線程有機會啓動或完成之前終止。

請記住,在日誌中看到「Second」和「Third」的順序是未定義的。在dispatch_async返回時,您現在有兩個併發線程,因此主隊列上的NSLog和後臺隊列可以按任一順序獲得輸出。

如果您在return語句之前阻止主線程(例如使用sleep),則應該看到來自兩個線程的所有日誌。