1.信号量
信号量一般用于线程间同步,多个线程获取一个共享资源时,该资源信号量的count值不小于0时,取得count的线程皆可访问共享资源(类似于流量QOS中的令牌桶\通行证)。当count值小于0时,获取该资源的线程阻塞等待其他线程释放资源count值重新大于0(类似于有空余令牌桶\通行证释放出来了).
2.优先级反转问题
假设有三个线程优先级从高到低:A (共享资源XXX) B(普通线程不竞争资源) C(共享资源XXX)。
按照正常的线程执行流优先级执行的结果是:A先执行完, B居中执行完, C最后执行完.
但现实中存在这么一个现象:
(1)C执行时先使用共享资源XXX,获取信号量正在运行;
(2)此时B投入ready队列准备运行,下一个时钟中断调度时,B优先级高于C,先调度执行B中.C被放在ready队列.
(3)A投入ready队列准备运行,下一个时钟中断调度时,B被调度放入ready队列,A调度运行,但此时A运行时需要获取共享资源XXX,而共享资源XXX被C占用,A因为没有共享资源XXX的“通行证”而被迫放入共享资源XXX的阻塞队列而放弃CPU。
(4)到此处,A被阻塞,B在ready队列,C在ready队列,CPU空着
继续调度,CPU优先运行高优先级B线程,直到执行完.接着执行C线程,C访问完共享资源XXX释放“通行证”,A被唤醒放入ready队列.
(5)到此处,A在ready队列、B执行完、C在ready队列.
下一个时钟中断,A优先调度直到执行完,再执行完C。
(6)到此处,所有线程执行完。但执行完的线程顺序:B A C,并非预期的顺序(A B C),
因此A和B线程称为优先级反转(优先级低的线程B先于优先级高的A线程执行完)
3.优先级反转造成的后果
暂无实际案例,但在实时嵌入式系统中会是灾难性的,实时操作系统中,每个任务的执行流时间片都是可控的,譬如线程每次最大执行时间不能超过xx 毫秒.
每个业务线程的执行优先级是根据业务重要性逻辑来定义的,假如优先级反转可能导致业务逻辑错乱.
现实举例(来自网络实例):
当年火星探路者号(Mars Pathfinder),就由于优先级反转,而导致了内部执行逻辑出错的bug:
在1997年7月4号发射后,在开始搜集气象数据之后没几天,系统(无故)重启了。
后来,被相关技术人员找到问题根源,就是,这个优先级反转所导致的,然后修复了此bug。
4.解决优先级反转方法
在优先级反转第(3)中,当现在A获取共享资源XXX时,发现占用资源XXX的C线程优先级低于自己,使用调度系统讲线程C的优先级临时上升到和自己线程A同等优先级.
这样在下一个时钟中断调度时,调度系统发现线程C优先级高于线程B,就先运行线程C了。线程C运行释放完“通行证”,A优先级最高先运行,B居中,C最后。
最终线程完整执行完顺序为:A B C