unix 中的线程调度
Posted
技术标签:
【中文标题】unix 中的线程调度【英文标题】:Thread scheduling in unix 【发布时间】:2013-07-19 13:42:17 【问题描述】:在 RR 调度策略中,如果一个低优先级线程锁定一个互斥体并因为另一个高优先级线程正在等待而被调度程序移除,会发生什么?
它还会释放低优先级线程持有的锁吗?
例如,考虑 3 个线程在 RR 调度策略中优先级为 10、20 和 30 的进程中运行。
现在在给定的时间点,低优先级线程 1 锁定互斥锁,并且仍在执行平均,而高优先级线程弹出并等待线程 1 持有的互斥锁。现在线程 2 进入图片,也需要线程 1 锁定了相同的互斥锁。
据我所知,根据调度算法,休眠或等待互斥量、信号量等的线程被删除,而其他线程,即使是低优先级的也被允许执行。它是否正确?如果是这样,在上面的示例中,最终高优先级线程等待低优先级线程完成,这没有任何意义。 如果所有线程都像我上面所说的那样设计,系统是这样工作的吗?
或 线程优先级应该设置成高优先级的不会依赖低优先级的互斥锁?
还有谁能解释一下调度在进程级别是如何工作的?我们如何为流程设置优先级?
【问题讨论】:
过去的问题是“线程太多,内核不够”,但多核革命正在迅速扭转这个问题。当您需要选择运行哪个线程时,线程优先级很有用,而不是当芯片设计人员想知道额外的内核是否仍然可以做一些有用的事情时。 【参考方案1】:通常,调度和锁在任何其他方面都是无关的,除了“等待线程在完成等待之前不会被调度”。拥有一个“阻止其他线程访问我的数据”的 MUTEX 是相当愚蠢的,但它仅在其他线程具有与当前线程相同或更低的优先级时才有效。
“低优先级持有高优先级线程'需要'的锁”的现象称为优先级反转,这是计算机理论中众所周知的场景。
有一些方案“暂时增加一个持有锁的线程的优先级,直到它释放锁到等待线程的最高优先级”(或者如果第一个等待线程的优先级高于当前线程,或者该主题的其他一些变化)。这样做是为了对抗优先级倒置——但它也有其他缺点,所以它并没有在所有操作系统/调度程序中实现(毕竟,它会影响其他线程而不是等待的线程)。
编辑:
互斥锁(或其他类似锁)的意义在于它可以防止两个线程同时访问相同的资源。例如,假设我们想通过一些相当冗长的处理(复杂的数学运算、从串行端口或网络驱动器获取数据等)更新五个不同的变量,但如果我们只处理其中两个变量,则其他一些过程使用这些会得到一个无效的结果,那么我们显然不能“放开”锁。
高优先级线程只需等待所有五个变量都被更新和低优先级锁定。
应用程序没有简单的解决方法来“修复”这个问题 - 当然,不要持有过多的锁 [而且我们可能实际上可以通过执行冗长的操作来解决上述问题处理 OUTSIDE 的锁,并且只在锁打开的情况下进行最后的“将其存储在 5 个变量中”。这将减少高优先级线程必须等待的潜在时间,但如果系统真的很忙,它不会真正解决问题。
关于这个主题写了整篇博士论文,我不是“如何编写调度程序”的专家——我很清楚一个人是如何工作的,就像我知道我的汽车引擎是如何工作的一样——但是如果有人给了我一堆合适的基本形状的钢和铝,以及所需的工具/工作空间并告诉我建造一个引擎,我怀疑它会很好用......调度器也是如此 - 我知道零件是什么调用,但不是如何构建一个。
【讨论】:
现在我明白了,我所想的可以在现实世界中发生。现在的问题是操作系统是否负责这种优先级调整,或者我们是否必须在我们的软件中处理它。如果是这样,你能指点我一个小例子吗?关于互斥锁,只有在没有竞争的高优先级线程时才授予正确的锁。但是我的问题是在低优先级线程获得锁之后,然后轮到高优先级线程。 @suresh,据我所知,股票 Linux 内核不会暂时增加线程的优先级来清除更高优先级线程想要的静音锁。但是,PREMPT_RT 内核补丁可以做到这一点。就我个人而言,我认为它是一个更好的调度程序,但是当我在做实时系统时,我会认为......至于其他 Unix,我认为那里没有太多的优先级反转解决方案。这在实时世界中更像是一种常态。【参考方案2】:如果高优先级线程需要在低优先级线程(互斥信号量等)上等待,则低优先级线程会暂时提升到与高优先级线程相同的优先级。
【讨论】:
这是否被定义为我不知道的“总是”?据我所知,“优先级提升”是在某些地方实施的技巧,但肯定不是在所有操作系统/调度程序中。 默认不是,需要使用PTHREAD_PRIO_INHERIT
mutex属性。见pubs.opengroup.org/onlinepubs/9699919799/functions/…
感谢您的链接。很明显,如果一个线程正在等待设置了 PTHREAD_PRIO_INHERIT 的相同互斥体,那么持有相同互斥体的线程将比等待线程以高优先级执行。基本上,这是通过定义互斥锁的优先级来实现的。
我在更一般的情况下回答,比如在等待套接字等(内核中有互斥体、信号量等)时
为了避免这种情况,我同意我们需要为互斥体设置优先级。但仍有一个问题尚未得到解答,即如果两个线程具有相同的互斥优先级会发生什么?【参考方案3】:
在低优先级线程解锁之前,高优先级线程不会拥有它所请求的锁。
为避免这种情况,我们可以使用信号量,任何其他线程都可以启动解锁,但在互斥锁中这是不可能的。
【讨论】:
以上是关于unix 中的线程调度的主要内容,如果未能解决你的问题,请参考以下文章