优先级倒挂(priority inversion)

优先级倒挂( priority inversion)在之前已经有所提及。其所指的是一个低优先级任务持有一个被高优先级认为所需要的共享资源。这样高优先级任务因资源缺乏处于受阻状态,一直到低优先级任务释放资源为止。 这样实际上造成了这两个任务的优先级倒挂。如果此时有其他优先级介于二者之间的任务,并且其不需要这个共享资源,则该中级优先级的进程将获得CPU控制,从面超越这两个任务。

在某些时候,优先级倒挂并不会造成损害。高优先级任务的延迟并不会被注意,因为低优先级进程最终会释放资源。但在其他一些时候,优先级倒挂则可能引起严重后果。如果一个高优先级进程一直不能获得资源,有可能造成系统故障,或激发事先定义的纠正措施、如系统复位。

如果高优先级进程在等待资源时不是阻塞等待,而是循环(繁忙)等待,则将永远无法获得所需资源。因为此时的低优先级进程无法与高优先级进程争夺CPU,从而无法执行,进而无法释放资源。这将造成高优先级进程无法获得资源而继续推进。

优先级倒挂还可能造成系统性能降低。低优先级进程之所以优先级低是因为其所执行的任务并不重要。例如,它们可能是批处理任务或其他非交互式任务。而高优先级任务执行的则是较为重要的任务,如为交互用户提高数据或实时任务。由于优先级倒挂造成低优先级任务在高优先级任务之前执行,系统的响应将降低,甚至实时系统的响应时间保证都有可能受到违反。

倒挂的解决方案

优先级倒挂的问题在上世纪70年代就已经发现,但却没有找到一个可以预测其发生的法。不过,虽然我们不能预测其发生,但却可以采取手段防止其出现。到目前为止,解决优级倒挂的办法可以归结为如下几种:

使用中断禁止

这种办法的核心是通过禁止中断来保护临界区。在采用此种策略的系统中只有两个优先级:可抢占优先级和中断禁止优先级。前者为一般进程运行时的优先级,后者为运行于临界区的进程的优先级。由于不存在第三种优先级,优先级倒挂无法发生。由于系统里只存在一个:(中断禁止操作在任何时候只能由一个进程执行),乱序不会发生,因此死锁也不会发生。由于临界区总能够不被打断而一直运行到结束,悬挂(hang)也不会发生。

这里需要注意的是所有中断都必须禁止。如果禁止的仅仅是一个特定的硬件设备的中断则硬件的中断优先处理机制将再次引人优先级倒挂。

在多CPU环境则使用一个简单的变种:单一共享标志锁。该方法在共享内存里面提供一个单一标志。所有CPU进入跨CPU临界区时都必须先获得该标志。由于CPU间的通信昂贵且慢,大多数此种系统都尽量不共享资源。因此这种方法在多数实际系统里都效果良好。

该方法普遍应用于简单的嵌入式系统。这种系统的特点是可靠性、简易性和资源需求低不过这种方法对程序员的要求较高,因此在程序设计时需要将临界区设计的很短,通常应该100微秒以下。而这个时间对于通用计算机来说很不现实。

优先级上限( priority ceiling)

在此种方式下,共享的mutex进程(操作系统代码)有其自身的高优先级。一个程序如进入mutex保护的临界区,将获得该临界区所具有的高优先级别。 此时如果其他试图访问 mutex的进程的优先级都低于mutex的优先级,则优先级倒挂将不会发生。

优先级继承(Priority inheritancc )

在此种方式下,当一个高优先级进程等待个低优先进程所持有的资源时,低优先级进程暂时获得高优先级进程的优先级别。 这样就能防止一个中间优先级的进程抢占低优先级进程而延长资源占用时间。在释放共享资源后,低优先级进程回到其原来的优先级别。

上一篇:Java多线程(三)


下一篇:RabbitMQ 优先级队列