2021/8/24 我想探知宇宙
2019年统考真题
问题描述:
有n(n>=3) 名哲学家围坐在一张圆桌边,每名哲学家交替地就餐和思考.在圆桌中心有m(m>=1)个碗,每两名哲学家之间有一根筷子。每名哲学家必须取到一个碗和两侧的筷子后,才能进餐,干饭后将碗和筷子放回原位,继续思考,为尽可能多的哲学家同时进餐,且防止出现死锁现象,进行PV操作和semaphore信号量定义。
资源全锁:
//定义semaphore信号量
semaphore bowl=n;//n个碗
semaphore chopstick[n];//n只筷子
semaphore mutex=1;//互斥取资源信号量
for(int i=0;i<n;i++)
chopstick[i]=1;//初始化信号量
Pi(){
//i号哲学家
while(1){
思考;
P(mutex);//互斥访问资源
if(bowl&&chopstick[i]&&chopstick[(i+1)%n]){
//左右筷子、婉都有
P(bowl);//拿碗
P(chopstick[i]);//拿左筷子
P(chopstick[(i+1)%n]);//拿右筷子
V(mutex);//拿完就释放互斥
哲学家干饭;
V(bowl);//释放碗
V(chopstick[i]);//释放左筷子
V(chopstick[(i+1)%n]);//释放右筷子
}
else
V(mutex);//资源不够释放互斥,满足尽可能多的哲学家同时进餐
}
}
运用了死锁避免
通过限制限制人数为n-1,取和其他资源的最小值 bowl=min{n-1,m}
如果资源类别>=2是要取所有资源的和n-1个人进餐人数的最小值
赋予最小值的信号量代表了同时进餐的人数
并且将赋予最小值的信号量放在进程的一开始的位置P(bowl);如果资源不满足就会阻塞
semaphore chopstick[n];//n只筷子
semaphore bowl=min{
n-1,m};//同时进餐的最大人数
for(int i=0;i<n;i++)
chopstick[i]=1;//初始化信号量
Pi(){
//i号哲学家
while(1){
思考;
P(bowl);//拿碗
P(chopstick[i]);//拿左筷子
P(chopstick[(i+1)%n]);//拿右筷子
干饭;
V(bowl);//释放碗
V(chopstick[i]);//释放左筷子
V(chopstick[(i+1)%n]);//释放右筷子
}
}
经典问题:同类不互斥,异类互斥 :电影院问题
问题描述:电影院有1,2,3种不同的电影(看不同的电影的人代表不同的进程),任意一时刻只能播放一种电影(放映厅互斥)选择当前正在播放的电影的人可以进入(不限制人数),最后一个观看电影的人结束放映厅的播放,看不同电影的人等待(说明第一个进入的占有放映厅,最后一个释放放映厅)
semaphore room=1;//放映厅
semaphore mutex_1=1;//第一种电影的互斥访问count_1信号量
int count_1=0;//第一种电影的观看人数
semaphore mutex_2=1;//第一种电影的互斥访问count_2信号量
int count_2=0;//第二种电影的观看人数
semaphore mutex_3=1;//第三种电影的互斥访问count_3信号量
int count_3=0;//第三种电影的观看人数
P1(){
//看第一种影片的人
P(mutex_1);//互斥访问count_1
if(count_1==0)//第一人
P(room);//占有放映厅
count_1++;//看电影1的人数+1
V(mutex_1);//访问婉count_1后释放
看片嘻嘻;
P(mutex_1);//互斥访问count_1
count_1--;//走就人数-1
if(count_1==0)//最后一个观看的人
V(room);//释放放映厅
V(mutex_1);//释放count_1
}
P2(){
//看第二种影片的人
P(mutex_2);//互斥访问count_2
if(count_2==0)//第一人
P(room);//占有放映厅
count_2++;//看电影2的人数+1
V(mutex_2);//访问婉count_2后释放
看片嘻嘻;
P(mutex_2);//互斥访问count_2
count_2--;//走就人数-1
if(count_2==0)//最后一个观看的人
V(room);//释放放映厅
V(mutex_2);//释放count_2
}
P3(){
//看第三种影片的人
P(mutex_3);//互斥访问count_3
if(count_3==0)//第一人
P(room);//占有放映厅
count_3++;//看电影3的人数+1
V(mutex_3);//访问婉count_3后释放
看片嘻嘻;
P(mutex_3);//互斥访问count_3
count_3--;//走就人数-1
if(count_3==0)//最后一个观看的人
V(room);//释放放映厅
V(mutex_3);//释放count_3
}
经典问题:P100 2.3.7 T19 南开大学弯路问题
问题描述:南开大学与天津大学之间有一条弯路,每次只允许一辆自行车通过,但中间安全岛M可供两端的两辆小车错车
NtoT(){
//从N到T
入口;
P(NT);//互斥从N到T只能一辆车
P(K);//到K路段
经过M岛;
V(K);//释放K路段
P(L);//申请L路段
出口;
V(NT);//通过,释放从N到T的互斥
}
TtoN(){
//从T到N
P(TN);//互斥从T到N只能一辆车
P(L);//到L路段
经过M岛;
V(L);//释放L路段
P(K);//申请K路段
出口;
V(TN);//通过,释放从T到N的互斥
}
王道OS强化课考试T1王道YYDS
问题描述:
某计算机学院,有男老师、男同学若干,没有女同学。学校运动会期间,老师和同学们都需要换上运动服参加运动。整个学院共用一个更衣室,更衣室很大。但是,老师们比较好面子,不想和别人一起更衣,而男同学们比较无所谓,可以和多个同学一起更衣。更衣室需要让老师优先使用。请使用P、V操作描述上述过程的互斥与同步,并说明所用信号量及初值的含义。
注意的是本题如果用书上的读者-写者问题-写优先是满足不了让老师优先使用的条件的
因此本题需要用真正的读者-写者-写优先
semaphore pri=1;//老师优先级
semaphore enter=1;//允许进入信号量
semaphore mutex_t=1;//老师互斥访问count_t
semaphore mutex_s=1;//学生互斥访问count_s
semaphore room=1;//更衣室互斥信号量
int count_t=0;//老师数
int count_s=0;//学生数
Teacher(){
//老师
P(enter);//是否允许进入
P(mutex_t);//老师互斥访问count_t
if(count_t==0){
//第一个老师
P(pri);//优先进入
}
count_t++;//老师数+1;
V(mutex_t);//释放老师变量count_t互斥信号量
V(enter);//释放共享
P(room);//占有更衣室
更衣室换衣服;
V(room);//换完衣服释放房间
P(mutex_t);//老师互斥访问count_t
count_t--;//老师换完衣服退出更衣室老师数-1
if(count_t==0){
//如果老师数为0了则暂时没老师要来
V(pri);//释放优先级
}
V(mutex_t);//释放老师互斥访问count_t
}
Student(){
//学生
P(pri);//等待老师
P(enter);//是否允许进入
P(mutex_s);//互斥访问学生人数count_s变量
if(count_s==0){
//第一个学生
P(room);//占有更衣室
}
count_s++;//学生人数+1
V(pri);//其他人可申请
V(mutex_s);//释放学生互斥信号
V(enter);//进入后释放信号量
更衣室更衣;
P(mutex_s);//互斥访问学生人数count_s变量
count_s--;//更衣完退出更衣室
if(count_s==0)//最后一个学生更衣
V(room);//释放更衣室
V(mutex_s);
}
经典问题:(有等待资源-椅子)忙(理发师在忙)则等待,没等待资源(没椅子了就拍屁股走人)
问题描述:理发店理有一位理发师、一把理发椅和n把供等候理发的顾客坐的椅子如果没有顾客,理发师便在理发椅上睡觉一个顾客到来时,它必须叫醒理发师如果理发师正在理发时又有顾客来到,则如果有空椅子可坐,就坐下来等待,否则就离开。
注意这里的if else是为了区分两种情况,一种是有资源,一种是没资源,if(有资源)则申请座位在更改资源变量chair后V(mutex)提高并发度。else 就是顾客到了但是没椅子了就走了直接释放V(mutex)
所以说与读者写者的if是不同的,因为读者写者的if纯粹就是互斥访问count修改count的值代表读者有多少个人,不会因为读者有多少个人就会影响其他读者,而理发师问题的wait变量的大小与chair资源的比较就会影响到其他顾客的行为(是离开还是申请chair)
semaphore consumers=0;//顾客人数
semaphore serve=0;//理发师提供服务
semaphore mutex_w=1;//互斥访问wait
int wait=0;//等待人数
int chairs=n;//椅子数量
Tony(){
//理发师
while(1){
P(consumers);//没有顾客就睡觉
P(mutex_w);//互斥访问wait变量
wait--;//等待人数-1
V(mutex_w);//访问完wait就释放
V(serve);//释放服务
为顾客服务理发;
}
}
Consumer(){
//顾客
顾客进门;
P(mutex_w);//互斥访问wait变量
if(wait<chairs){
//有椅子则申请椅子
wait++;//等待人数+1
V(mutex_w);//访问完wait就释放
V(consumsers);//通知有顾客来了
P(serve);//申请服务
接收服务
}
else //没椅子
V(mutex_w);//释放互斥
}
思想:同步问题:前V后P 生产者消费者的马甲很多同时有些题目很难
史诗级难题:P98 2.3.7 T10 小和尚打水-大和尚喝水
问题描述:某寺庙有小和尚、老和尚若干,有一水缸,由小和尚提水入缸供老和尚饮用。水缸可容10桶水,水取自同一井中。水井径窄(互斥)每次只能容一个水桶取水。水桶总数为3个。每次入缸取水仅为一桶水,且不可同时进行。试给出有关从缸取水、入水的算法描述
semaphore bucket=3;//水桶个数
semaphore empty=10;//水缸空闲容量
semaphore well=1;//水井互斥取水
semaphore vat=1;//水缸互斥取水/放水
semaphore water=0;水缸有水容量
child(){
//小和尚
while(1){
P(empty);//保证水缸中还需加水
P(bucket);//申请桶
拿桶;
P(well);//互斥水井取水
井中取水;
V(well);//取完水释放水井
//P(empty);若在此处加就可能发送死锁,缸中水满,桶全被小和尚拿了,老和尚打不了水
P(vat);//互斥水缸
放水入缸;
V(vat);//释放水缸
V(water);//释放缸中的一桶水,即缸中加了一桶水
V(bucket);//还桶;
}
}
adult(){
//老和尚
while(1){
P(water);//保证水缸中有水
P(bucket);//申请水桶
拿桶;
//P(water);可能发生死锁,缸中没水,桶全被老和尚拿了,小和尚没桶到水井打水
P(vat);//互斥水缸
缸中取水;
V(vat);//释放水缸
喝水;
V(empty);//释放
V(bucket);//还桶;
}
}
此处表明了当有地方多次连续出现P时要考虑前后的关系,以防发生死锁
方法:①设置顾客号数i,设置叫号号数j,通过比对i和j来判断
②直接用PV操作阻塞
如P97 T7面包师
面包师有很多面包,由n名销售人员推销,每名顾客进店后取一个号,并且等待叫号,当一名销售人员空闲时,就叫下一个号。试设计一个使销售人员和顾客同步的算法。
semaphore mutex_i=1;//互斥访问i变量
semaphore mutex_j=1;//互斥访问j变量
int i=0;//顾客的取号号数
int j=0;//销售人员的叫号号数
consumer(){
//顾客
进店;
P(mutex_i);//互斥取号
取号;
i++;//号数加1,下一个顾客的编号
V(mutex_i);//取完号释放互斥
等待被叫号;
}
salex(){
//x号销售人员
while(1){
P(mutex_j);//互斥访问j
if(j<i){
//有顾客
叫号;
j++;
V(mutex_j);//访问完j,释放互斥
销售服务;
}
else
V(mutex_j);//无顾客,休息
}
}
semaphore mutex=1;//互斥取号
semaphore consumers=0;//顾客数
semaphore serve=0;//销售人员提供服务
consumer(){
进店;
P(mutex);//互斥取号
取号;
V(mutex);//释放互斥
V(consumers);//释放顾客信号量,通知有客人
P(serve);//申请服务
接收服务;
}
sale(){
while(1){
P(consumers);//没客人休息
V(serve);//释放服务
销售面包,为客户服务;
}
}