过桥问题
一条南北方向架设的、可双向通行的单车道简易桥,最大载重负荷为4辆汽车。使用P、V操作写出任一车辆通过该简易桥的管理算法。
这是一个读者-写者问题
semaphore N2Smutex = 1,S2Nmutex = 1;//互斥访问
semaphore mutex = 1;//互斥使用桥,单车道:哪边先抢就让哪边先过
semaphore weight = 4;//最大载重4辆车
int s2ncount = 0,n2scount = 0;//等待过桥的车辆
N2S() //从南向北
{
while(1){
P(N2Smutex);
if(n2scount==0){//自己是这个方向的第一辆车,肩负着抢占桥使用权的使命
P(mutex);
}
n2scount++;
V(N2Smutex);
P(weight);
过桥
V(weight)
P(N2Smutex);
n2scount--;
if(n2scount=0){//自己是这个方向的最后一辆车,归还桥的使用权
V(mutex);
}
V(N2Smutex);
}
}
S2N()
{
while(1){
P(S2Nmutex);
if(s2ncount==0){
P(mutex);
}
s2ncount++;
V(S2Nmutex);
P(weight);
过桥
V(weight)
P(S2Nmutex);
s2ncount--;
if(s2ncount==0){
V(mutex);
}
V(S2Nmutex);
}
}
睡眠理发师问题
理发店里有一位理发师、一把理发椅和n把供等候理发的顾客坐的椅子。
如果没有顾客,理发师便在理发椅上睡觉。当一个顾客到来时,他必须先叫醒理发师。
如果理发师正在理发时又有顾客到来,如果有空椅子可做,顾客就坐下来等待;
如果没有空椅子,顾客就离开。用信号量解决理发师和顾客进程的同步问题。
发现理发师和顾客互为生产者消费者,两者相互阻塞对方的进程,用互斥信号量seat记录空余椅子数量,customers为等待理发的顾客数,barbers为等候顾客的理发师数。分析一下题目,理发师睡觉其实代表的就是理发师进程的阻塞,无需设置一个额外的变量去记录理发师是否醒着,在P操作申请资源的过程中,有资源的话就不睡觉,而没有资源的话就睡眠。
关于P操作的理解:往P操作以后的部分,说明已经申请到了相应的资源,如果没有相应资源,则会一直阻塞在P操作那里,不会进入到P操作的后面的部分
我们可以先实现一个顾客不“让权等待”的baseline,然后在baseline的部分加以修改
semaphore customers = 0;//记录等待理发的顾客数,用来阻塞理发师进程
semaphore barbers = 0;//记录正在等候顾客的理发师数,用来阻塞理发师进程
semaphore seat = n;//椅子的数量
customer(){
while(1){
P(seat);
V(customers);//向理发师发送信号
P(barbers);//接受理发师的信号
V(seat);
haircut();
}
}
barber(){
while(1){
P(customers);
V(barbers);
haircut();
}
}
main(){
Cobegin
customer();
barber();
Coend
}
接着我们需要实现顾客“让权等待”,把信号量seat变成可访问整型变量chairs和waiting
注意几点:
1.进程barber和信号量barbers变量名注意不要重复了
2.顾客只有剪一次头发,不用套while循环
semaphore mutex = 1;//互斥访问座位数量
semaphore customers = 0;//记录等待理发的顾客数,用来阻塞理发师进程
semaphore barbers = 0;//记录正在等候顾客的理发师数,用来阻塞理发师进程
int waiting = 0;//此时有多少个正常等待的顾客
int chairs = n;//共享资源,一共有几把椅子
barber(){
while(1){
P(customers);//若无顾客,理发师睡眠
P(mutex);//上锁
waiting--;
V(barbers);//理发师去为其中一个顾客剪头发
V(mutex);//解锁
cut_hair();//剪头发
}
}
customer(){
P(mutex);//waiting上锁
if(waiting < chairs){//有空的椅子,找位置坐下
waiting++;
V(customers);//呼叫理发师
V(mutex);//waiting解锁
P(barbers);//无空闲的理发师,顾客坐着
cut_hair();//顾客坐下等待理发
}else{
V(mutex);//人数已满,离开
}
}
main(){
Cobegin
customers();
barber();
Coend
}