前文链接:https://blog.csdn.net/C__herry/article/details/121689849
(历时太长,太过激动,没写完直接发布了...)
信号量机制的缺点
- 易读性差
- 不利于修改和维护
- 正确性难以保证
采用信号量机制编写并发程序时,对临界区的执行会分散在各个进程中。
管程
管程是一种并发性的结构,是由一个或多个过程、一个初始化序列和局部数据组成的软件模块。
组成:
- 管程名
- 局部于管程的共享变量说明
- 对该数据结构进行操作的一组过程或函数
- 对局部于管程的数据设置初始值的语句
特点:
- 只能通过管程中的进程而不能用其他外部过程访问局部数据变量
- 进程通过调用管程的过程而进入管程
- 每一时刻只能有一个进程在管程中执行,任何其他调用管程的进程将被挂起直至管程可用为止
习题
例1: 试用P操作和V操作描述下图所示的程序或语句间的前驱关系
semaphore a=0, b=0, c=0, d=0, e=0, f=0; void P1() { S1; signal(a); } void P2() { wait(a); S2; signal(b); signal(c); } void P3() { wait(b); S3; signal(d); } void P4() { wait(c); S4; signal(e); } void P5() { wait(d); wait(e); S5; signal(f); } void P6() { wait(f); S6; } void main() { parbegin( P1(), P2(), P3(), P4(), P5(), P6() ); }
例2: 有一个阅览室,共有100 个座位,读者进入时必须先在一 张登记表上登记,该登记表
为每一位读者列一表目,包括座号和读者姓名等,读者离开时要消掉登记的信息。试用P操作和V操作描述读者进程之间的同步关系。semaphore seats=100; //座位个数 semaphore mutex=1; //互斥的访问 void reader() { while(true){ wait(seats); wait(mutex); 填写登记表; signal(mutex); 在阅览室内活动; wait(mutex); 消掉登记信息; signal(mutex); signal(seats); } }
例3: 从读卡机上读进N张卡片,然后复制一份, 要求复制出来的卡片与读进来的卡片完全信一致。这一工作由三个进程get、copy和put以及两个缓冲区buffer1和buffer2 完成。
进程get的功能是把一张卡片上的信息从读卡机上读进buffer1;进程copy的功能是把buffer1中的信息复制到buffer2;进程put的功能是取出buffer2中的信息并从打印机上打印输出。试用P操作和V操作完成这三个进程间的并发运行的关系,并指明信号量的作用及初值。
分析:为两个缓冲区分别设置一个empty和full信号量:empty1=1 : buffer1不为空;full1=0 : buffer1不为满; empty2=1 : buffer2不为空;full2=0 : buffer2不为满。
get()的条件:buffer1不为满
copy()的条件:buffer1不为空,buffer2不为满
put()的条件:buffer2不为空
semaphore empty1=1, full1=0, empty2=1, full2=0; void get() { while(true){ wait(empty1); 将数据存入buffer1; signal(full1); } } void copy() { while(true){ wait(full1); wait(empty2); 将数据从buffer1拷贝到buffer2; signal(full2); signal(empty1); } } void put() { while(true){ wait(full2); 将buffer2中的数据打印输出; signal(empty2); } } void main() { parbegin( get(), copy(), put() ); }
例4: 请用信号量解决以下的“过独木桥”问题:同方向的行人可连续过桥,当某方向
有行人过桥时,另方向的行人必须等待;当某一方向无人过桥时, 另方向的行人可以过桥。分析:假设桥的两端为东和西,记两边在桥上的人数分别为ecount和wcount,初始值为0;设置两个信号量emutex和wmutex分别表示ecount、wcount的互斥访问,另外设置一个信号量mutex表示过桥的互斥访问,初始值均为1。
int ecount=0, wcount=0; semaphore emutex=1, wmutex=1, mutex=1; void east() { while(true){ wait(emutex); if(ecount==0) wait(mutex); ecount++; signal(emutex); 通过独木桥; wait(emutex); ecount--; if(ecount==0) signal(mutex); signal(emutex); } } void west() { while(true){ wait(wmutex); if(wcount==0) wait(mutex); wcount++; signal(wmutex); 通过独木桥; wait(wmutex); wcount--; if(wcount==0) signal(mutex); signal(wmutex); } } void main() { parbegin( east(), west() ); }