主进程中添加任务到GCD的main queue会卡死,而如果用生成的queue却正常运行: dispatch_queue_t serialQueue = dispatch_queue_create("squeue", NULL);
// dispatch_queue_t mainQueue = dispatch_get_main_queue();
NSLog(@"Main Queue-->%@", dispatch_get_main_queue()); dispatch_sync(serialQueue, ^{ //如果用mainQueue就卡死
NSLog(@"Task 1-->%@", [NSThread currentThread]);
});在main()中执行没问题,如果dispatch_sync改用mainQueue的话就卡死了。squeue和mainQueue都是主线程里创建的串行队列,为什么前者正常,后者会卡死?是否可认为,sync函数本身是在主线程的主队列中执行,所以sync用mainQueue的话当然会死锁因为它自己就是mainQueue的第一个任务;
而用新生成的serialQueue,它的第一个任务就是添加的block,此时的mainQueue第一个任务只是sync,所以能顺利执行?
// dispatch_queue_t mainQueue = dispatch_get_main_queue();
NSLog(@"Main Queue-->%@", dispatch_get_main_queue()); dispatch_sync(serialQueue, ^{ //如果用mainQueue就卡死
NSLog(@"Task 1-->%@", [NSThread currentThread]);
});在main()中执行没问题,如果dispatch_sync改用mainQueue的话就卡死了。squeue和mainQueue都是主线程里创建的串行队列,为什么前者正常,后者会卡死?是否可认为,sync函数本身是在主线程的主队列中执行,所以sync用mainQueue的话当然会死锁因为它自己就是mainQueue的第一个任务;
而用新生成的serialQueue,它的第一个任务就是添加的block,此时的mainQueue第一个任务只是sync,所以能顺利执行?
解决方案 »
- xcode4 tableview测试编译成功,显示空白一片, 求救。
- iphone SDK与开发所需要的硬件配置问题,知道的都来看看吧
- [新手急问] 一个关于UIButton的问题
- windows下有什么方法能对ipa安装文件进行重新签名,在PC上完成的
- iOS中怎么样使用protobuf支持64位的iPhone5s?
- APNS的生产证书如何使用
- NSData转化NSString遇到问题了
- ios平台下G.711编码的音频转换成PCM Linear
- 静态库.a 文件没有完全链接进可执行程序
- IOS开发扫描二维码获取值后,http拿数据,系统崩溃
- 求一个IOS的 xmpp即时通讯 放在xcode就可以用的,
- 抛泪小白求不相助Undefined symbols for architecture arm64:
main_queue是串行队列,当queue调用sync函数块,会阻塞当前队列,等待block执行,但是这个block永远没有机会执行,当前队列就永远阻塞,造成死锁dispatch_sync(dispatch_get_main_queue() ^{
NSLog(@"Task 1-->%@", [NSThread currentThread]);
});
http://stackoverflow.com/questions/19180661/sync-dispatch-on-current-queue/19181474#19181474
问题就是,这个在mainQueue里的block为什么不会执行?
或者换个一个问法,在main()函数中,dispatch_queue_t squeue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);生成的squeue处于哪个线程?本来,个人理解为squeue应该在主线程里,当把block插入到squeue里,因为只有该block一个任务,所以是正常的。但如果有嵌套任务如下:
dispatch_sync(squeue, ^{
NSLog(@"Task 1-->%@", [NSThread currentThread]);
dispatch_sync(squeue, ^{
NSLog(@"Task 2-->%@", [NSThread currentThread]);
});
});此时Task 2是squeue的第2个任务,它必须等到串行队列的第1个任务Task 1执行完才能执行;而squeue的第1个任务要想执行完,就要往下执行Task 2的block,所以2个任务的起始条件互为结果,造成线程的直接制约,死锁。
另外,Task 1无论是sync还是async都会死锁,因为死锁的原因是任务调度顺序,而不是同步异步。以上是原先的理解,现在回到提问本身来。
那么,同样是主线程里的串行队列dispatch_get_main_queue(),为什么就会卡死?dispatch_async(dispatch_get_main_queue() ^{
NSLog(@"Task 1-->%@", [NSThread currentThread]);
});
NSRunLoop *rl = [NSRunLoop currentRunLoop];
[rl run];为了撇清同异步影响,将sync换成async,同时为了让异步调用确实得到执行,运行一个runloop防止main()退出。
在main()中执行会直接卡死。此时是异步调用,按理说block插入到mainQueue中不用等待结果就可以返回了吧,为何也会卡死?
问题就是,这个在mainQueue里的block为什么不会执行?
或者换个一个问法,在main()函数中,dispatch_queue_t squeue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);生成的squeue处于哪个线程?本来,个人理解为squeue应该在主线程里,当把block插入到squeue里,因为只有该block一个任务,所以是正常的。但如果有嵌套任务如下:
dispatch_sync(squeue, ^{
NSLog(@"Task 1-->%@", [NSThread currentThread]);
dispatch_sync(squeue, ^{
NSLog(@"Task 2-->%@", [NSThread currentThread]);
});
});此时Task 2是squeue的第2个任务,它必须等到串行队列的第1个任务Task 1执行完才能执行;而squeue的第1个任务要想执行完,就要往下执行Task 2的block,所以2个任务的起始条件互为结果,造成线程的直接制约,死锁。
另外,Task 1无论是sync还是async都会死锁,因为死锁的原因是任务调度顺序,而不是同步异步。以上是原先的理解,现在回到提问本身来。
那么,同样是主线程里的串行队列dispatch_get_main_queue(),为什么就会卡死?dispatch_async(dispatch_get_main_queue() ^{
NSLog(@"Task 1-->%@", [NSThread currentThread]);
});
NSRunLoop *rl = [NSRunLoop currentRunLoop];
[rl run];为了撇清同异步影响,将sync换成async,同时为了让异步调用确实得到执行,运行一个runloop防止main()退出。
在main()中执行会直接卡死。此时是异步调用,按理说block插入到mainQueue中不用等待结果就可以返回了吧,为何也会卡死?
以上关于异步调用mainQueue,本人的说法是错误的,由于看混了sync和async。
更正:async调用mainQueue是正常的。请关注前面的问题。
如下:
//-------------------------------------------
int main(void) {
dispatch_queue_t queue = dispatch_queue_create(“com.somecompany.queue”, nil);
dispatch_async(queue, ^{ //任务1
[self goDoSomethingLongAndInvolved];
dispatch_sync(queue, ^{ // 任务2
NSLog(@"Situation 1");
});
});
return 0;
}
这种场景下包了2层的的调用会死锁,任务1和任务2起始条件互为执行结果,形成直接制约,死锁。
//-------------------------------------------
int main(void) {
dispatch_queue_t queue = dispatch_queue_create(“com.somecompany.queue”, nil);
dispatch_sync(queue, ^{ // 任务1
NSLog(@"Situation 1");
});
return 0;
}
这种场景正常。注意,这里只包了1层,queue是主线程生成的串行队列。
//-------------------------------------------
int main(void) {
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{ // 任务1
NSLog(@"Situation 1");
});
return 0;
}
这种场景线程卡死。注意,这里只包了1层,queue是主队列。
那么,对比上一场景,同样只包了1层同样是主线程里的串行队列同样sync调用,为何上一个正常这个卡死?
结合第一个场景来推理,场景3卡死是因为sync函数调用时本身就运行在主队列中?
调用的dispatch_sync函数一直得不到返回,main queue被阻塞,而我们的block又需要等待main queue来执行它,死锁愉快的产生了。
慢慢领悟吧!!!
而回答无一不在阐述main()中sync调用会导致死锁的现象力图解释头尾互相等待会死锁。其实如果有认真看提问的话,解答时说一句“因为sync就运行在主队列”或“语句都运行在主队列”就够了。
我知道这是一个很基础的问题,但要的解答却不是网上那种囫囵吞枣的答案。同样的问题描述,还是老外比较认真,针对问题核心给予解答:
Everything in your program runs on the main queue except for code that you explicitly dispatch onto another queue. Code on the main queue will always run on the main thread. Code dispatched on another queue may or may not run on the main thread.
当然也可能是自己太菜,连所有语句都是运行在主队列上这种大家都普遍默认的常识都不懂,所以才会大费周章的解释死锁现象。因为以前用c,不太有iOS主队列的概念。