Objective-C使用dispatch_semaphore时出现主线程死锁问题
死锁原因
你提交的代码当前运行在主线程上下文,触发死锁的流程如下:
- 主线程执行
dispatch_semaphore_create(0)创建初始值为0的信号量 - 调用
dispatch_async(dispatch_get_main_queue(), ^{...})向主队列提交待执行的block,主队列是串行队列,提交的block必须等主线程当前正在执行的任务结束后才会被调度 - 主线程紧接着执行
dispatch_wait(waitSem, DISPATCH_TIME_FOREVER),因为信号量初始值为0,主线程直接进入阻塞休眠状态,等待信号量唤醒 - 负责调用
dispatch_semaphore_signal唤醒信号量的block还在主队列等待调度,主线程已经被阻塞无法执行该block,最终形成永久死锁。
解决方案
分两种适配场景:
- 场景1:当前代码必须运行在主线程
不要使用信号量做等待,把dispatch_wait之后需要执行的逻辑,直接移到提交到主队列的block内部即可,修改后示例:
dispatch_async(dispatch_get_main_queue(), ^{ // do something else // 把原来dispatch_wait之后要执行的逻辑写在这里 });
- 场景2:当前代码可迁移到后台线程执行
把整段逻辑放到后台队列执行,此时dispatch_wait阻塞的是后台线程,主线程可以正常调度待执行的block发送信号量,不会死锁,修改后示例:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_semaphore_t waitSem = dispatch_semaphore_create(0); dispatch_async(dispatch_get_main_queue(), ^{ // do something else dispatch_semaphore_signal(waitSem); }); dispatch_wait(waitSem, DISPATCH_TIME_FOREVER); // 原来dispatch_wait之后要执行的逻辑写在这里 });
内容的提问来源于stack exchange,提问作者jackie_G
相关产品推荐
相关产品推荐

