6.1一种新的同步机制——管程:高级同步机制
管程出现的原因:信号量机制的不足,程序编写困难,易出错。
管程:
- 是一个特殊的模块;
- 有一个名字;
- 由关于共享资源的数据结构及在其上操作的一组过程组成。
进程与管程的区别:进程只能通过调用管程中的过程来间接的访问管程中的数据结构。
管程作为一种同步机制,需要解决:
- 互斥——管程管理了一些共享资源,因此管程是互斥进入的,即有一个进程在调用管程中的过程,就不允许其他进程调用,主要是为了保证管程中的数据结构的数据完整性;管程的互斥性是由编译器负责保证的。
- 同步——管程中设置条件变量及等待/唤醒操作以解决同步问题,等待/唤醒操作可以让一个进程或线程在条件变量上等待(此时,应先释放管程的使用权),也可以通过发送信号将等待在条件变量上的进程或线程唤醒。
在应用管程的过程中,会出现这样的状况:当一个进入管程的进程Q执行等待操作等待某种条件完成,将管程的操作权释放后,P进程进入管程并执行唤醒操作对Q进程进行唤醒,此时,管程中存在两个同时活动的进程。对于这样的状况,采取以下三种方法解决:
- P等待Q执行——Hoare管程;
- Q等待P继续执行——MESA管程,Q等待的位置有所改变;
- 规定唤醒操作为管程中最后一个可执行的操作——Hansen管程,在并发pascal语言中实现。
6.2 Hoare管程
Hoare管程说明:
- 因为管程是互斥进入的,所以当一个进程试图进入一个已被占用的管程时,应当在管程的入口处等待,为此,管程的入口处设置一个进程等待队列,称作入口等待队列;
- 如果进程P唤醒进程Q,则P等待Q执行,如果进程Q执行中又唤醒进程R,则Q等待R执行。。。如此,在管程内部可能会出现多个等待进程。为此,在管程内需要设置一个进程等待队列,称为紧急等待队列,紧急等待队列的优先级高于入口等待队列的优先级。
Hoare管程——条件变量的实现——条件变量:在管程内部说明和使用的一种特殊类型的变量。假设我们声明一个条件变量C,则对于条件变量,只能执行wait和signal操作。
- wait(c):如果紧急等待队列非空,则唤醒第一个等待者;否则释放管程的互斥权,执行此操作的进程进入C链末尾。
- signal(c):如果C链为空,则相当于空操作,执行此操作的进程继续执行;否则唤醒第一个等待者,执行此操作的进程进入紧急等待队列的末尾。
6.3管程的应用
管程实现的两个主要途径:
- 直接构造——效率高;
- 间接构造——用某种已经实现的同步机制去构造。
管程的应用:
- 用管程解决生产者消费者问题
monitor ProducerConsumer Procedure producer;
condition full,empty; begin
integer count; while true do
begin
procedure insert(item:integer);
begin item=produce_item;
if count==N then wait(full); ProducerConsumer.insert(item);
insert_item(item);count++; end
if count==1 then signal(empty); end;
end;
Procedure consumer;
function remove:integer; begin
begin while true do
if count==0 then wait(empty); begin
remove =remove_item;count--; item=ProducerConsumer.remove;
if count==N-1 then signal(full); consume_item(item);
end;
end
count:=0; end;
end monitor;
6.4 MESA管程
由于Hoare管程需要两次额外的进程切换,因此采用MESA来改进:由Hoare中的signal操作改为MESA中的notify操作。
notify:当一个正在管程中的进程执行notify(x)时,它使得x条件队列得到通知,发信号的进程继续执行。
使用notify需要注意:
- notify的结果:位于条件队列头的进程在将来合适的时候且当处理器可用时恢复执行;
- 由于不能保证在它之前没有其他进程进入管程,因而这个进程必须从新检查条件——用while循环取代if语句;
- 因此使用MESA管程的缺点是导致对条件变量至少多一次额外的检测(但不再有额外的进程切换),并且对等待进程在notify之后何时运行没有任何限制。
对notify的改进:
- 给每个条件原语关联一个监视计时器,不论是否被通知,一个等待时间超时的进程将被设为就绪态。因为当该进程被调度执行时,会再次检查相关条件,如果条件满足则继续执行。超时可以防止如下情况的产生:当某些进程在产生相关条件的信号之前失败时,等待该条件的进程就会被无限制地推迟执行而处于饥饿状态。
- 引入broadcast:使所有在该条件上等待的进程都被释放并进入就绪队列。其优点是,a.当一个进程不知道有多少进程将被激活时,这种方式是非常方便的;b.当一个进程难以准确判定将激活哪个进程时,也可使用广播。
Hoare管程与MESA管程的比较:
- MESA管程优于hoare管程之处在于MESA管程错误比较少;
- 在MESA管程中,由于每个过程在收到信号都重新检查管程变量,并且由于使用了while结构,一个进程不正确的broadcast广播或发信号notify不会导致收到信号的程序出错。收到信号的程序将检查相关的变量,如果期望的条件没有满足,它会重新继续等待。
管程小结:
管程:抽象数据类型,有一个明确定义的操作集合,通过它且只有通过它才能操纵该数据类型的实例。
实现管程结构必须保证以下几点:
- 只能通过管程的某个过程才能访问资源;
- 管程是互斥的,某个时刻只能有一个进程或线程调用管程中的过程。
条件变量:为提供进程与其他进程通信或同步而引入——wait/signal或wait/notify或wait/broadcast。
6.5线程库PTHREAD中的同步机制
解决互斥问题:通过对互斥量提供相应的操作保护临界区;
解决同步问题:通过对条件变量提供相应的操作解决同步。
其中,pthread_cond_wait的执行分解为三个主要动作:
- 解锁;
- 等待;当收到一个解除等待的信号(pthread_cond_siganl或者pthread_cond_broad_cast)之后,pthread_cond_wait马上需要做的动作是:
- 上锁。
pthread实现的是一个mesa管程。
6.6进程间通信机制
通信机制存在的理由:
- 信号量及管程的不足;
- 不适用多处理器情况。
进程通信机制中一个非常典型的形式是消息传递——send&receive原语。适用于分布式系统、基于共享内存的多处理机系统、单处理机系统,可以解决进程间的同步问题、通信问题。
基本通信方式:
- 消息传递
- 共享内存
- 管道(利用一个缓冲传输介质——内存或文件链接两个相互通信的进程)
- 套接字
- 远程过程调用。其中后两者适用于网络或者分布式系统。
6.7典型操作系统中的IPC机制
UNIX:管道、消息队列、共享内存、信号量、信号
LINUX:用户程序使用(管道、消息队列、共享内存、信号量、信号、套接字)。内核同步机制:原子操作、自旋锁、读写锁、信号量、屏障、BKL。
WINDOWS:同步对象:互斥对象、时间对象、信号量对象、临界区对象、互锁变量。套接字、文件映射、管道、命名管道、邮件槽、剪贴板、动态数据交换、对象连接与嵌入、动态链接库、远程过程调用。
LINUX的进程通信机制继承了Unix、bsd、system v的IPC机制。
2956

被折叠的 条评论
为什么被折叠?



