一.2009(45)题目分析及背景
1.1. 题目背景分析
本题是一个典型的生产者--消费者问题,经过分析,我们可以得知P1( )的基本操作有produce()和put()两个,P2()的基本操作有getodd()和countodd()两个,P3()的基本操作有geteven()和counteven()两个.我们经过分析,可以得知,定义信号量odd控制P1()和P2()之间的同步,定义信号量even控制P1()和P3()的同步,empty控制生产者和消费者进程之间的同步,控制缓冲区的容量,mutex控制互斥访问缓冲区,接下来放一些生产者----消费者进程的知识点
1.2. 问题分析
该问题需要注意的几点:
- 在缓冲区为空时,消费者不能再进行消费,这种情况下需要分偶数和奇数的情况,缓冲区有偶数才可以取偶数,缓冲区有奇数才可以取奇数
- 在缓冲区为满时,生产者不能再进行生产
- 在一个线程进行生产或消费时,其余线程不能再进行生产或消费等操作,即保持线程间的同步
- 注意条件变量与互斥锁的顺序
二.题目代码
1.信号量定义
Semaphore mutex=1; //互斥使用缓冲区
Semaphore odd=0; //缓冲区当前有奇数的个数
Semaphore even=0; //缓冲区当前有偶数的个数
Semaphore empty=N; //缓冲区当前有多少空间
P1(){
while(1){
int x=produce();//生成一个正整数
P(empty); //先看当前缓冲区是否有空间
P(mutex); //再互斥访问缓冲区
put(x);
V(mutex); //保证先实现对缓冲区的互斥访问结束
if(x%2!=0) //当前数为奇数
V(odd); //缓冲区奇数+1
else //当前数为偶数
V(even); //缓冲区偶数+1
}
}
P1(){
while(1){
P(odd); //先P一个奇数
P(mutex); //实现对缓冲区互斥访问
getodd(); //取一个奇数
V(mutex); //对缓冲区互斥访问结束
V(empty); //缓冲区空闲单元数+1
countodd();//统计奇数个数
}
}
P2(){
while(1){
P(even); //收到P1发来的信号,P一个偶数
P(mutex); //互斥访问缓冲区
geteven(); //取一个偶数
V(mutex); //互斥访问结束
V(empty); //缓冲区容量+1
counteven(); //统计偶数个数
}
}
三.2010(45)题目题目背景
3.1.题目背景分析
互斥与同步关系的分析:
我们经简短分析可得知,题目内需要竞争使用的资源有1.座位 2.取号机,顾客进程需要对这两类临界资源进行互斥的访问,而在事件的执行中,我们可以观察得知,在营业员叫号时,需要保证顾客中有人取号,因此,顾客进程i取号与营业员叫号两个事件的发生有先后顺序的关系,因此本题在顾客进程i取号与营业员叫号之间有同步关系,需要在顾客进程i中对变量customer先V而在营业员程序中P
四. 题目代码
信号量
Semaphore mutex1=0; //对取号机进行互斥访问
Semaphore customer=0; //同一时刻,仅有一位营业员为顾客服务
Semaphore seat=10; //座位数,为共享资源
Process 顾客i(){ //顾客进程
P(seat); //申请座位
P(mutex1); //申请取号机
从取号机取一个号码;
V(mutex1); //取号结束
V(customer); //通知营业员有人要求服务
等待叫号;
V(seat); //得到叫号,释放座位
获取服务;
}
Process 营业员(){
while(true){
P(customer); //有顾客时才可以叫号
叫号;
为顾客服务;
}
}