OS X 上的 GCD 死锁,但 iOS 上没有

GCD deadlock on OS X but not on iOS

我的 viewDidLoad

中有此代码
- (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

这在某些执行上也有所不同。有时它会打印 "First, Second, Third, Fourth, 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 不同?如果有人能解释发生了什么,我将不胜感激

关于Mac你没有死锁。这是 main 完成的简单情况,应用程序在后台线程有机会启动或完成之前终止。

还要记住,在日志中看到 "Second" 和 "Third" 的顺序是未定义的。到 dispatch_async returns 时,您现在有两个并发线程,因此主队列和后台队列上的 NSLog 可以按任意顺序获得输出。

如果您在 return 语句之前阻塞主线程(例如使用 sleep),您应该会看到来自两个线程的所有日志。