Bruce Powel Douglass大师介绍-CSDN博客https://blog.csdn.net/ChatCoding/article/details/134665868嵌入式软件开发从小工到专家-CSDN博客https://blog.csdn.net/ChatCoding/article/details/135297955C嵌入式编程设计模式源码-CSDN博客https://blog.csdn.net/ChatCoding/article/details/134819019
最高锁定模式虽然可以减少优先级反转的情况,但并不能保证完全避免死锁。其他模式,如有序锁定模式(Ordered Locking Pattern)和同时锁定模式(Simultaneous Locking Pattern),则提供了避免死锁的其他方法。
7.4.1 抽象
最高锁定模式是解决无界阻塞/无界优先级反转问题的另一种解决方案。
- 最高锁定模式为每个资源定义了一个优先级上限。
-
在最高锁定模式下,如果任务没有阻塞任何更高优先级的任务,则其优先级不会提升。只有当任务阻塞了一个或多个更高优先级的任务时,任务的优先级才会提升到其所持有资源中最高的优先级。
HLP(Highest Locker Protocol):
- 一步到位: HLP 会直接将任务的优先级提升到资源的上限优先级。
- 快速响应: HLP 可以快速响应高优先级任务的资源请求,避免高优先级任务长时间阻塞。
PIP(Priority Inheritance Protocol ):
- 逐步提升: PIP 会逐步提升任务的优先级,每当被阻塞任务的优先级高于当前优先级,则提升一次持有资源任务的优先级。
- 响应速度慢: PIP 的响应速度相对较慢,因为需要多次提升才能达到最终的优先级。
- 这限制了优先级反转:任务的优先级只能提升到其所持有的资源的最高优先级,因此,因资源竞争而导致的优先级反转最多发生一次。
- 它与优先级继承模式不同:任务在拥有资源时被更高优先级的任务抢占(这个更高优先级的任务不需要当前已被锁定的资源),不会发生链式阻塞。
在最高锁定模式(Highest Locker Pattern)中,当一个任务在拥有资源时被抢占,不会发生链式阻塞,因为如果它需要这个资源,它的优先级就不会比资源的优先级上限还高,所以它无法抢占。因此,就不会有一个任务在等待另一个任务释放资源时被阻塞,进而导致链式阻塞。
只要任务在拥有资源时不自行挂起,这种设计避免了任务在拥有资源时被抢占导致的链式阻塞。
- 任务在拥有资源时主动挂起自己,可能会出现链式阻塞,类似于优先级继承模式(Priority Inheritance Pattern),因此可能会出现死锁情况。
任务在拥有资源时主动挂起可能会导致链式阻塞,因为这种行为可能违反了最高锁定模式的规则。在最高锁定模式中,任务在获取资源时会提升到该资源的优先级上限,以此来限制优先级反转。
然而,如果任务在持有资源的同时挂起自己,它就无法释放资源,如果有其他任务需要这些被挂起任务持有的资源,它们也会被阻塞。
如果这些被阻塞的任务又持有其他资源,那么又会有更多的任务因为等待这些资源而被阻塞,从而形成一条阻塞链。这种链式阻塞可能会涉及多个任务和资源,最终可能导致系统的运行效率降低,甚至出现死锁的情况。
为了避免死锁,应该确保任务在拥有资源时不会挂起自己。如果系统允许任务在拥有资源时挂起自己,那么就需要像处理优先级继承模式那样计算最坏情况下的阻塞时间(遍历链式阻塞的最长情况)。
- 只要拥有资源的任务不将自己挂起,就不会出现死锁的情况。
为了避免死锁,需要打破死锁的四个必要条件中的至少一个。最高锁定模式主要是通过限制优先级反转来解决无界阻塞/无界优先级反转问题,但它并没有直接解决死锁问题。相比之下,优先级上限模式(Priority Ceiling Pattern)旨在限制最大优先级反转到单一级别,并完全防止基于资源的死锁。
7.4.2 问题
解决资源竞争而导致的:无限优先级反转。
7.4.3 模式结构:
图 7-10:最高锁定模式
最高锁定模式的结构元素与优先级继承模式类似,如图 7-10 所示。唯一的区别在于共享资源新增了名为 priorityCeiling 的属性。
该模式通过为每个可锁定资源定义一个上限优先级priorityCeiling 。priorityCeiling 仅比资源最高优先级客户端的优先级稍高一级,并在设计时确定。当资源被锁定时,锁定任务的优先级会提升到该资源的上限优先级。
7.4.4 协作角色:
抽象线程 (Abstract Thread)
- 抽象类,不可直接实例化。
- 与调度器关联,保证接口一致性。
- 抽象线程是一个“活动”对象,意味着它创建时会创建一个线程用于运行。它通过组合关系包含一些被动对象,这些被动对象在“活动”对象的线程中执行。
具体线程 (Concrete Thread)
- 可实例化的抽象线程子类。
- 用于包含执行系统实际工作的“语义对象”。
- 提供将这些语义对象纳入并发架构的直接方式。
互斥锁 (Mutex)
互斥锁是一个互斥信号量对象,一次只允许一个调用者通过。共享资源的操作每当调用相关服务时都会调用它,在启动服务之前将其锁定,并在服务完成后将其解锁。
- 一次只允许一个调用者通过互斥信号量访问共享资源。
- 共享资源的服务调用会锁定它,完成后解锁。
- 尝试调用已锁定的资源则会被阻塞,直到互斥锁解锁。
- 互斥信号量向调度器发送信号,通知调度器当前活动线程尝试调用互斥信号量,并提供互斥信号量 ID (用于以后释放时解锁)和入口点(线程继续执行的位置)。
调度器 (Scheduler)
- 调度器根据线程优先级协调多个线程的执行,始终运行就绪队列中具有最高优先级的任务。
- 当“活动”线程对象创建时,它会调用 createThread 操作为其创建一个任务。
- 当任务未被阻塞或抢占,调度器会调用 StartAddr 地址从头开始执行此任务,
- 当任务已被阻塞或抢占,调度器则会调用 EntryPoint 地址继续执行此任务。
- 在最高锁定模式中,当互斥锁试图访问已被锁定的资源时,调度器会:
- 阻塞请求任务,将其放入阻塞队列中。
- 将拥有资源的任务的优先级提升到共享资源的 priorityCeiling。
共享资源 (Shared Resource)
- 共享资源是多个线程共享的对象。为了保证系统正常运行,所有共享资源要么是可重入的,要么必须受到保护。
- 当线程尝试使用受保护的资源时,会检查资源关联的互斥锁。如果被锁定,则将任务放入阻塞队列,并将其重新进入点记录在 TCB 中。
- 共享资源有一个名为 priorityCeiling 的常量属性,其值要比能访问该资源的最高优先级的任务的优先级要高一级,这确保了当资源被锁定时,使用该资源的其他任务不能抢占它。
任务控制块 (Task Control Block, TCB)
- TCB包含与其对应的线程对象相关的调度信息,包括线程的优先级、默认启动地址以及在完成之前被抢占或阻塞时的入口地址。
- 调度器为每个现有线程维护一个 TCB 对象。TCB 记录线程的当前优先级(可能因资源访问和阻塞而提升)及其初始默认优先级。