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
),您应该会看到来自两个线程的所有日志。
我的 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
),您应该会看到来自两个线程的所有日志。