信号量应用题
1. 生产者-消费者问题(互斥+同步)
生产者把消息放入缓冲区,消费者从中取出信息,二者互斥访问
semaphore mutex = 1;//互斥访问缓冲区,因为有多个缓冲区资源
semaphore empty = n;//n个空闲区资源,内部互斥
semaphore full = 0;//将消息视作资源,用于同步
producer(){//生产者
while(1){
P(empty);//跟消费者进行同步,消费者——>生产者
P(mutex);//互斥访问区域
//将数据放入缓冲区
V(mutex);//互斥访问区域
V(full);//跟消费者进行同步,生产者——>消费者
}
}
consumer(){//消费者
while(1){
P(full);//跟生产者进行同步,生产者——>消费者
P(mutex);//互斥访问区域
//从缓冲区取出数据
V(mutex);//互斥访问区域
V(empty);//跟生产者进行同步,消费者——>生产者
}
}
//桌上一盘子,爸爸放苹果,妈妈放橘子,儿子吃橘子,女儿吃苹果(爸妈互斥放盘,爸女同步、妈儿同步)
semaphore plate = 1,apple = 0,orange = 0;
dad() mom() son() daughter()
2. 读者-写者问题(互斥)
多个读者可以同时读、只允许一个写者写,写和读互斥
int count = 0;//公共计数器需要互斥访问
semaphore mutex = 1;//互斥访问计数器
semaphore rw = 1;//互斥进行读和写
semaphore w = 1;//互斥的提出申请资源
writerr(){//写者
while(1){
P(w);//互斥申请资源
P(rw);//互斥读写
//进行写操作
V(rw);//互斥读写
V(w);//允许其他程序申请资源
}
}
reader(){//消费者
while(1){
P(w);//互斥申请资源
P(mutex);//互斥访问count
if(count==0) P(rw);//初始时,互斥读写
count++;
V(mutex);//互斥访问count
V(w);//允许其他程序申请资源
//读取数据
P(mutex);//互斥访问count
count--;
if(count==0) V(rw);//释放读写权限
V(mutex);//互斥访问count
}
}
3. 哲学家进餐(互斥)
semaphore chopsticks[5]={1,1,1,1,1};//筷子资源
semaphore mutex = 1;//互斥申请筷子,本质上把取筷子弄成原子操作
Pi(){//i号哲学家进程
while(1){
P(mutex);//互斥申请资源
P(chopsticks[i]);//取左边筷子
P(chopsticks[(i+1)%5]);//取右边筷子
V(mutex);//互斥申请资源
//吃
V(chopsticks[i]);//放回左边筷子
V(chopsticks[(i+1)%5]);//放回右边筷子
}
}
4. 吸烟者问题(同步)
int num = 0;//递增判断分配资源类型
semaphore offer1 = 0,offer2 = 0,offer3 = 0;//用于生产者->消费者同步
semaphore finish=0;//用于消费者->生产者同步
5. 读取奇偶(同步+互斥)
一进程随机产生数放入缓冲区,另两进程分别读取奇数偶数
semaphore mutex = 1;//互斥访问缓冲区
semaphore empty = N;//空闲区n个资源
semaphore odd=0,even=0;//用于奇数、偶数进程同步
P1(){//生产者
while(1){
x = preoduce();//生成一个数
P(empty);//消耗资源
P(mutex);//互斥访问缓冲区
//数据x放入缓冲区
V(mutex);//互斥访问缓冲区
if(x%2==0) V(even);//同步偶数进程
else V(odd);//同步奇数数进程
P(mutex);//互斥访问门
//出门
V(mutex);//互斥访问门
V(empty);//释放资源
}
}
P2(){//消费奇数
while(1){
P(odd);//消耗奇数
P(mutex);//互斥访问
//从缓冲区得到奇数
V(mutex);//互斥访问
V(empty);//释放资源
//给奇数计数
}
}
P3(){//消费偶数
while(1){
P(even);//消耗奇数
P(mutex);//互斥访问
//从缓冲区得到偶数
V(mutex);//互斥访问
V(empty);//释放资源
//给偶数计数
}
}
6. A类B类产品(互斥)
每次只能放入一种,A-B<M,B-A<N
semaphore mutex = 1;//互斥访问仓库
semaphore Sa = M-1,Sb = N-1;//对AB资源在某种限度内的互斥访问,可知两者的资源上限是相互制约的
访问一次A类资源,同时要释放B类资源,同理B类也是,实现一定弹性的互斥访问
7. 面包取号叫号(互斥访问公共变量)
int i=0,j=0;//取号数和叫号数
semaphore mutex_i=0,mutex_j=0;//互斥访问公共变量
8. 参观博物馆(互斥)
博物馆可容纳500人,仅有一个出入口
semaphore mutex = 1;//互斥访问门
semaphore capacity = 500;//空闲资源数
Pi(){
while(1){
P(empty);//消耗资源
P(mutex);//互斥访问门
//进门
V(mutex);//互斥访问门
//参观
P(mutex);//互斥访问门
//出门
V(mutex);//互斥访问门
V(empty);//释放资源
}
}
9. 生产车间和装配车间
两个生产车间生产A、B类零件,放到容量为10的两个货架上,装配工人每次取A、B零件组装
semaphore empty1=10,empty2=10;//容量大小
semaphore full1=0,full2=0;//资源数量
semaphore mutex1 = 1,mutex2 = 1;//互斥访问缓冲区货架
10. 取水饮水(同步+互斥)
小和尚给老和尚取水,取水互斥,存水互斥,水缸容量10,水桶3个
semaphore well=1;//互斥访问水井
semaphore vat = 1;//互斥访问水桶
semaphore empty = 10;//水缸容量
semaphore full = 0;//水缸水量
semaphore pail = 3;//水桶个数
11. 合作计算打印(同步)
semaphore s1=1,s2=0,s3=0;//实现进程的同步
semaphore sb=0,sy=0,sz=0;//判断对应数是否已经输入,用于同步
12. 银行取号叫号
银行有十个空位,互斥访问取号机,等待叫号
semaphore empty=10;//空位数量为10
semaphore full=0;//顾客初始为0
semaphore mutex = 1;//互斥访问取号机
semaphore service = 0;//用于营业员——>顾客叫号同步
P1(){//顾客
while(1){
P(empty);//等待消耗空位
P(mutex);//互斥使用取号机
//从取号机取号
V(mutex);//互斥使用取号机
V(full);//新增等待客户
P(service);//等待叫号
}
}
P2(){//营业员
while(1){
P(full);//等待客户
V(service);//叫号
V(empty);//释放座位
}
}
13. 交通管制
不允许异向行驶,允许同方向多辆车行驶
int countSN=0,countNS=0;//记录两个方向车辆数量
semaphore mutexSN=1,mutexNS=1;//互斥访问公共变量
semaphore mutex = 1;//互斥访问桥
14. 自行车生产线(同步)
生产线上有N个箱子,工人1加工一个车架,工人2加工一个车轮,工人3取一个车架两个车轮组装
semaphore empty = N;//空闲位置
semaphore wheel = 0;//车轮数用于同步
semaphore frame = 0;//车架数用于同步
semaphore s1 = N-1;//车轮最大数量,防死锁
semaphore s2 = N-2;//车架最大数量,防死锁
15. 理发师(同步)
一把理发椅和n把供等待椅子,没有客户理发师在理发椅睡觉,没有椅子客户不等待
int chairs = n;//椅子数
int waiting = 0;//等待数
semaphore customers = 0;//客户——>理发师同步,唤醒理发师
semephore barbers = 0;//理发师——>客户同步,理发师准备剃头
semephore mutex = 1;//互斥访问公共变量,即互斥查看椅子状态
16. 电影院看影片
三部影片循环播放
semaphore s =1;//互斥看电影
semaphore s1=1,s2=1,s3=1;//互斥访问公共变量
int count1 = 0,count2=0,count3=0;//公共变量记录看当前电影人数
17. 安全岛错车
安全岛允许两辆车停留错车(两个方向各一辆),L路段和K路段只允许一辆车通过(在互斥变量的访问和释放上体现方向性即可)
semaphore T2N = 1, N2T = 1;//两个方向行驶互斥
semaphore L = 1, K =1;//两个路段的互斥
18. 消费者连续取
semaphore mutex1=1,mutex2=1;//互斥对缓冲区进行存取,以及使连续取成为原子操作,这里用for循环
semaphore empty = n;/空闲资源
semaphore full = 0;//资源
19. 邮箱辩论
A邮箱容量M,B邮箱容量N,初始A邮箱x个邮件,B邮箱y个邮件
semaphore full_a = x,full_b = y;//初始邮件数
semaphore empty_a = M-x, empty_b = N-y;//还可以存放的邮件数
semaphore mutex1=1,mutex2=1;//互斥访问邮箱A,互斥访问邮箱B
A(){
while(1){
P(full_a);
P(mutex1);
//取邮件
V(mutex1);
V(empty_a);
//回答问题
P(empty_b);
P(mutex2);
//放入邮件
V(mutex2);
V(full_b);
}
}
//另一程序基本一致
20. 三线程(互斥)
三个全局变量x、y、z,线程1访问x、y(只读),线程2访问y,z(只读),线程3访问z,y(读写)
semaphore mutex1 = 1;//用于y变量读1和写3的互斥
semaphore mutex2 = 1;//用于y变量读2和写3的互斥
semaphore mutex3 = 1;//用于z变量的互斥读写
21. 哲学家进餐(加碗并优化)
m个碗和n个哲学家
semaphore chopsticks[n];
for(int i=0;i<n;i++) chopsticks[i]=1;//初始化进行互斥使用
semaphore bowl = min(n-1,m);//防止死锁,最多只有bowl个人进行申请资源
Pi(){//i号哲学家进程
while(1){
P(bowl);//互斥申请资源
P(chopsticks[i]);//取左边筷子
P(chopsticks[(i+1)%n]);//取右边筷子
//吃
V(chopsticks[i]);//放回左边筷子
V(chopsticks[(i+1)%n]);//放回右边筷子
V(bowl);//释放资源
}
}
22. 操作同步
A、B、C、D、E五个操作,C在A、B完成之后,E在C、D完成之后
semaphore SAC=0,SBC=0,SCE=0,SDE=0;//四个同步关系
A(){V(SAC)}
B(){V(SBC)}
C(){P(SAC)P(SBC)V(SCE)}
D(){V(SDE)}
E(){P(SCE)P(SDE)}