虽然信号量机制是一种既方便、又有效的进程同步机制,但每个临界资源都要自备同步操作 wait(s) 和 signal(s) ,这就使大量的同步操作分散在各个进程中,不仅给系统的管理带来了麻烦,还会因为同步操作的使用不当而导致系统死锁。为了解决这些问题,便诞生了一种新的同步工具——管程。
信号量机制的三点不足:
• 临界区、进入区和退出区都由用户编写
• 信号量操作原语分散在各程序代码中,由进程来执行,系统无法有效控制、管理
• wait 和 signal 操作的错误使用,编译程序和操作系统都无法发现、纠正,可能导致死锁
一、管程的定义
管程是操作系统的资源管理模块,由 代表共享资源的数据结构 以及 对该共享数据结构 实施操作的一组过程 所组成。
二、管程的组成
① 管程的名称
② 局部于管程的共享数据结构说明
③ 对该数据结构进行操作的一组过程
④ 对局部于管程数据设置初始值的语句
三、管程如何实现进程互斥
(1)同一管程内的过程仅能访问同一管程内的数据结构,同样,同一管程内的数据结构也只能被同一管程内的过程访问。(也就是完全封闭的)
(2)每次只允许一个进程进入管程,执行管程内的过程(操作管程内的临界资源),从而实现了进程互斥。
(3)管程类型提供了一组由程序员定义的、在管程内互斥的操作,确保一次只有一个进程在管程内活动。
(4)进程通过管程请求临界资源未满足时,管程将其加入等待队列。
四、带有条件变量的管程
1. 为什么引入条件变量
考虑一种情况,当一个进程调用了管程,在执行过程中却被阻塞或挂起,在此期间它都不会释放管程(所谓的占着茅坑不拉屎),以至于其它管程都无法进入管程,被迫长时间等待。
为了解决这个问题,引入了条件变量。简单来说就是:当管程中的进程被阻塞或挂起时,让它释放管程。
2. 原理详解
(1)进程阻塞或挂起的原因有很多,因此在管程中设置多个条件变量,每种条件变量代表了一种阻塞或挂起的类型。
(2)每个条件变量保存了一个链表(等待队列),用于记录因该原因而阻塞或挂起的所有进程。
(3)对条件变量的访问只能在管程中进行。
(4)管程中每个条件变量都须说明,形式为 condition x , y ;
(5)对条件变量的操作仅有 wait 原语 和 signale 原语。
(6)当正在调用管程的进程检测到 x 条件满足时,该进程就需要被挂起或阻塞,则调用 x.wait; 将自己插入 x 条件变量的等待队列中,并释放管程,直到 x 条件变化。
(7)当正在调用管程的进程检测到 x 条件变化时,则调用 x.signal; 重新启动一个因 x 条件而被阻塞或挂起的进程;如果 x 的等待队列是空的,则继续执行原进程,而不产生任何结果。