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

什么是的优先级反转(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.xdnf.cn/news/15925.html

相关文章:

  • Syncthing实时共享同步数据 服务器数据备份软件(linux、windows)
  • 《程序员修炼之道》第一二章读书笔记
  • 【ChatOpenAI】常用方法详解
  • Helm常用命令大全(2025最新版)
  • 二分查找-69.x的平方根-力扣(LeetCode)
  • 大语言模型置信度增强实战指南
  • (LeetCode 每日一题) 1233. 删除子文件夹 (排序)
  • 统计学习方法
  • 堆堆堆,咕咕咕
  • python的多线程无法并行只能并发,why?
  • GA-BP遗传算法优化BP神经网络数据生成,采用SVM分类模型评估
  • roslaunch 文件的核心语法和使用技巧
  • Linux内核设计与实现 - 第5章 系统调用
  • docker构建springboot镜像
  • 数据结构之图
  • 【办公类-107-02】20250719视频MP4转gif(削减MB)
  • MyBatis分页神器PageHelper深度解析
  • 深入解析文件操作(上)- 二进制文件和文本文件,流的概念,文件的打开和关闭
  • 计算机网络1.1:计算机网络在信息时代的作用
  • Redis常见线上问题
  • Javascript进程和线程通信
  • VIT速览
  • Nestjs框架: RxJS 核心方法实践与错误处理详解
  • XSS漏洞----基于Dom的xss
  • 混沌趋势指标原理及交易展示
  • python爬虫之获取渲染代码
  • Python 数据分析模板在工程实践中的问题诊断与系统性解决方案
  • 探索量子计算与法律理论的交叉领域
  • Zephyr环境搭建 - Board GD32A503
  • 力扣 hot100 Day49