什么是线程优先级翻转?我们首先来看一张图:
优先级翻转图示
有三条线程A、B、C,线程优先级是A > B > C,在时间[0,t1]时,C线程访问共享资源S,标记为C(S)
,此时A,B等待事件到来被挂起。t1时刻,A线程有任务就绪(普通的任务,非访问共享资源S),此时时间片[t1, t2]交给任务A执行任务,标记任务A
。t2时刻,A线程的任务执行完毕,并试图访问共享资源S,标记为A(S)
。但是因为此时C线程正在访问S----C(S)
,所以[t2 , t3]时间片A(S)
只能等待C(S)
完成。t3时刻,任务B就绪,因为B优先级高于C,所以[t3, t4]时刻,任务B得到执行。然后[t4, t5]时间片内C(S)
访问完毕后,在[t5, t6]时刻A(S)
才得到执行。这就造成了高优先级的任务被低优先级的任务抢先执行,就叫做优先级翻转。
解决优先级翻转有两种方法:
优先级天花板
优先级天花板是当任务申请某资源时,把该任务的优先级提升到可访问这个资源的所有任务中最高优先级。这种方法简单易行,不比进行复杂的判断,不管任务是否阻塞了高优先级任务的运行,只要任务访问共享资源都会提升任务的优先级。优先级继承
优先级继承是当任务A申请共享资源S时,如果S正在被任务C访问,比较A和C的优先级,发现C的优先级小于A优先级,将任务C优先级提升到A的优先级,待C释放S资源后,在恢复C到原有优先级。
结论:
- 使用锁的代码应尽量短
- 使用小锁替代大锁,减少抢占机会