iOS中同步派发的工作项是否无论队列类型都始终在主线程执行?
关于iOS中dispatch_sync执行线程的问题
答案是否定的,同步派发的工作项并非始终在主线程执行,它的执行线程完全由你调用dispatch_sync的那个线程决定。
核心原理
dispatch_sync是同步阻塞调用:调用它的线程会暂停,直到派发的工作项执行完成。在大多数无死锁风险的场景下,系统会直接在当前调用线程上执行这个工作项,不会额外切换线程。
你未覆盖的反例场景
你之前的测试应该都是在主线程中调用dispatch_sync,所以工作项都在主线程执行。但只要换个调用线程,结果就会不同:
场景1:子线程中同步派发非主队列
比如在全局队列的子线程里同步派发任意非主队列,工作项会直接在这个子线程执行:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSLog(@"调用dispatch_sync的线程:%@", [NSThread currentThread]); // 子线程 // 同步派发自定义并发队列 dispatch_queue_t customConcurrentQueue = dispatch_queue_create("com.example.concurrent", DISPATCH_QUEUE_CONCURRENT); dispatch_sync(customConcurrentQueue, ^{ NSLog(@"同步工作项的执行线程:%@", [NSThread currentThread]); // 和上面的子线程一致 }); });
场景2:子线程中同步派发主队列
这种情况比较特殊:主队列的任务只能在主线程执行,所以dispatch_sync会阻塞当前子线程,直到主线程空闲并执行完这个工作项,此时工作项的执行线程是主线程:
dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"调用dispatch_sync的线程:%@", [NSThread currentThread]); // 子线程 dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"同步主队列的工作项线程:%@", [NSThread currentThread]); // 主线程 }); });
⚠️ 注意:如果在主线程中同步派发主队列,会直接导致死锁——主线程等待自己执行完任务,而任务又等着主线程空闲,陷入无限等待。
总结
- 若在主线程调用
dispatch_sync:无论派发至哪种非主队列,工作项都会在主线程执行;若派发至主队列则触发死锁。 - 若在子线程调用
dispatch_sync:- 派发至非主队列:工作项在当前子线程执行
- 派发至主队列:工作项在主线程执行(但会阻塞子线程直至任务完成)
内容的提问来源于stack exchange,提问作者jbalt
相关产品推荐
相关产品推荐

