当前位置: 首页 > news >正文

什么是的优先级反转(Priority Inversion) 和 优先级继承(Priority Inheritance)?

这个问题涉及多线程编程中的优先级反转(Priority Inversion)优先级继承(Priority Inheritance) 机制。理解这两个概念对编写高性能、实时性强的程序至关重要。我将通过具体例子和对比来解释。

一、优先级反转:为什么高优先级线程会被“卡住”?

场景描述

假设系统中有三个线程:

  • 高优先级线程 H(如实时控制任务)
  • 中优先级线程 M(如后台计算)
  • 低优先级线程 L(如日志记录)

执行顺序

  1. L 获取锁,开始执行临界区代码。
  2. H 就绪,抢占 L 并开始执行。
  3. H 需要同一把锁,但锁被 L 持有,H 被阻塞,进入等待状态。
  4. L 恢复执行,但此时M就绪(M优先级高于L),M抢占L并开始执行。
  5. M 持续运行,导致 L 无法继续执行,进而无法释放锁 → H 被无限期阻塞(即使 H 优先级最高)。
问题本质

高优先级任务的执行被中优先级任务延迟,而中优先级任务与锁本身无关。这就是优先级反转,严重破坏了实时系统的确定性。

二、优先级继承:如何解决反转问题?

机制说明

高优先级线程 H 阻塞于低优先级线程 L 持有的锁时:

  • L 临时继承 H 的优先级(成为系统中优先级最高的线程)。
  • 其他中等优先级线程(如 M)无法抢占 L
  • L 快速执行完临界区代码,释放锁
  • L 恢复原优先级,H 获取锁继续执行。
关键效果
  • 减少 H 的等待时间:L 因优先级提升而不被 M 抢占,能尽快释放锁。
  • 避免无限期阻塞:H 的等待时间被严格限制在 L 执行临界区的时间内。

三、对比示例:有/无优先级继承的差异

无优先级继承
时间线   线程状态                  说明
0-10     L 执行(获取锁)         L 进入临界区
10-15    H 就绪,抢占 L           H 需要锁,但被 L 阻塞
15-20    L 恢复执行               L 继续临界区代码
20-30    M 就绪,抢占 L           M 与锁无关,但优先级高于 L
30-40    M 执行                  H 持续等待
40-45    L 恢复执行               M 执行完毕,L 继续
45-50    L 释放锁,H 获取锁       H 等待了 35 个时间单位
有优先级继承
时间线   线程状态                  说明
0-10     L 执行(获取锁)         L 进入临界区
10-15    H 就绪,抢占 L           H 需要锁,但被 L 阻塞
15-20    L 恢复执行(继承 H 优先级) L 优先级临时提升,高于 M
20-25    L 释放锁,H 获取锁       L 快速完成临界区,H 仅等待 15 个单位
25-30    H 执行                  H 正常执行
30-40    M 执行                  M 在 H 之后执行

四、优先级继承的局限性

  1. 无法完全消除反转
    若有多个锁存在,可能出现链式反转(L 持有锁1被 H 阻塞,L 又需等待另一个低优先级线程持有的锁2)。

  2. 临时优先级提升的副作用
    L 可能因优先级提升而抢占其他高优先级任务(如与锁无关的 H2)。

  3. 需要系统支持
    内核需提供原子操作(如 Linux 的 futex)来实现优先级继承,否则性能开销较大。

五、适用场景

  • 实时系统(如航空航天、医疗设备):严格控制任务响应时间。
  • 锁持有时间短:若临界区代码执行时间较长,优先级继承的效果有限。
  • 优先级差异大:线程优先级跨度大时,反转问题更严重。

六、代码示例(伪代码)

// 线程 H
void* high_priority_thread(void* arg) {pthread_mutex_lock(&mutex);  // 若锁被 L 持有,H 阻塞// L 此时继承 H 的优先级critical_section();        // H 获取锁后执行pthread_mutex_unlock(&mutex);return NULL;
}// 线程 L
void* low_priority_thread(void* arg) {pthread_mutex_lock(&mutex);  // L 获取锁,优先级为原始低优先级// 若 H 此时请求锁,L 优先级被提升critical_section();        // L 快速执行临界区pthread_mutex_unlock(&mutex);  // L 释放锁,恢复原优先级return NULL;
}

总结

优先级继承通过临时提升锁持有者的优先级,确保高优先级任务的等待时间被限制在临界区内,从而减少反转带来的不确定性。这是实时系统中平衡性能与确定性的重要手段,但需合理设计锁粒度和优先级体系。

http://www.dtcms.com/a/289652.html

相关文章:

  • 【软件测试】使用ADB命令抓取安卓app日志信息(含指定应用)
  • 【AI论文】递归混合体:学习动态递归深度以实现自适应的令牌级计算
  • faster-lio与fast-lio中如何修改雷达的旋转角度
  • 单片机启动流程和启动文件详解
  • 2025年渗透测试面试题总结-2025年HW(护网面试) 59(题目+回答)
  • 商业秘密保护:从法律理论到企业实战
  • 牛客-删除公共字符
  • 股票账户数据及其数据获取
  • 【时时三省】(C语言基础)字符指针作函数参数
  • 如何系统性备考网络规划师
  • TCL --- 列表_part1
  • 第459场周赛
  • 开源社区贡献指南:如何通过Three.js插件开发提升企业技术影响力?
  • 【JS逆向基础】数据库之mysql
  • Python,GPU编程新范式:CuPy与JAX在大规模科学计算中的对比
  • 【企业架构】TOGAF概念之一
  • Linux基础命令详解:从入门到精通
  • 详解Mysql解决深分页方案
  • 试用SAP BTP 05A:AI服务-Document Information Extraction
  • Python桌面版数独(二版)-增加4X4、6X6
  • 小型支付项目3-5:检测未接收到或未正确处理的支付回调通知
  • 论文笔记:Seed: Bridging Sequence and Diffusion Models for RoadTrajectory Generation
  • LLM指纹底层技术——KV缓存压缩
  • 嵌入式通信DQ单总线协议及UART(一)
  • 是否可以将“进化”应用到软件系统的设计中?
  • 049_List接口(ArrayList / LinkedList / Vector)
  • Three.js + WebGL 深空星波粒子动画特效制作详解
  • 30天打牢数模基础-模拟退火算法讲解
  • 零基础100天CNN实战计划:用Python从入门到图像识别高手
  • k8s:离线添加集群节点