1️⃣ 核心结论
QoS 继承是指当一个任务提交到队列时,如果提交线程的 QoS 高于目标队列任务的 QoS,系统会临时提升队列任务的 QoS,保证高优先级任务不会被低优先级任务阻塞。
- 本质:防止高优先级任务被低优先级队列拖慢 → 保证响应性
- 临时提升仅在调度时生效,任务完成后恢复队列默认 QoS
2️⃣ QoS 继承机制
2.1 什么时候继承
-
当高 QoS 线程
dispatch_async或sync提交任务到 低 QoS 队列 -
系统检测:
- 任务提交线程 QoS > 队列 QoS
- 临时提升任务 QoS 到提交线程 QoS
-
执行完毕后:
- 队列恢复原本的 QoS
2.2 技术原理
- GCD 每个队列维护 默认 QoS
- 任务提交时会有 effective QoS = max(队列 QoS, 提交线程 QoS)
- 调度时线程池会优先调度 effective QoS 高的任务
3️⃣ 真实场景示例
假设有一个后台队列处理下载任务,但 UI 有高优先级任务触发:
// 后台队列(低 QoS)
let backgroundQueue = DispatchQueue(label: "backgroundQueue", qos: .background)
// UI 高优先级线程
DispatchQueue.global(qos: .userInitiated).async {
print("用户触发操作")
// 提交任务到后台队列
backgroundQueue.async {
print("后台下载任务处理用户请求")
}
}
解释
- 用户在主线程或
.userInitiated队列触发事件 - 背景队列默认 QoS =
.background - 提交任务到后台队列时,GCD 会 临时提升这个任务的 QoS 为
.userInitiated - 系统优先调度此任务,避免高优先级 UI 被阻塞
- 任务完成后,队列恢复原本 QoS
✅ 效果:高优先级用户请求不会被后台低 QoS 队列拖慢
4️⃣ 常见使用场景
-
UI 操作触发后台任务
- 用户点击按钮触发后台数据处理
- 确保处理及时,不被后台低 QoS 任务阻塞
-
链式异步任务
- 高 QoS 任务在串行队列中触发多个 async
- 后续任务会继承 QoS,保持优先级
-
全局队列的 QoS 提升
- 提交到
.utility或.background全局队列 - 高 QoS 提交线程 → 临时提升任务 QoS
- 提交到
5️⃣ 总结
- QoS 继承 = 任务优先级保护机制
- 避免高优先级任务被低优先级队列拖慢
- 在 GCD 中,实际任务执行的 QoS = max(队列 QoS, 提交线程 QoS)
- 临时提升,只影响调度,不改变队列默认 QoS