You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

同步等待AVAssetExportSession.exportAsynchronously完成是否会触发死锁?

问题结论

这种写法存在明确的死锁风险,AVAssetExportSession.exportAsynchronously 并没有官方保证回调一定会运行在其他队列上。

具体原因

  • 苹果官方文档对该方法的回调队列没有做强制约定:如果你没有主动设置 AVAssetExportSession 的 completionQueue 属性,回调默认会派发到任意全局后台队列执行;但如果你自行指定了 completionQueue,回调就一定会跑到你指定的队列上执行。
  • 死锁的触发场景非常容易复现:如果调用 foo() 的当前队列,刚好和回调执行的队列是同一个串行队列,就会出现死锁:当前线程被 semaphore.wait() 阻塞挂起,回调任务在同一个串行队列里等待执行,永远等不到 semaphore.signal() 触发。
  • 额外风险:如果是在主队列调用这个 foo() 方法,哪怕没有触发死锁,阻塞主线程也会直接导致UI完全无响应,违反苹果的主线程优化规则。

优化方案

如果确实有同步等待导出完成的需求(比如当前已经在后台串行队列执行任务,需要保证执行顺序),可以主动指定独立的回调队列,避免和当前调用队列重合:

// 注意:该方法绝对不可以在主队列调用
func foo() {
    let semaphore = DispatchSemaphore(value: 0)
    // 主动指定独立的并发队列作为回调队列,避免和当前队列冲突
    session.completionQueue = DispatchQueue(label: "custom.export.completion", attributes: .concurrent)
    session.exportAsynchronously {
        defer {
            semaphore.signal()
        }
        // 处理导出结果逻辑
    }
    semaphore.wait()
}

最佳实践:更推荐全程用异步逻辑处理导出流程,不要强行把异步方法转同步,能彻底规避死锁、线程阻塞的问题。

内容的提问来源于stack exchange,提问作者whatdayistoday

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 00:27:04