PV操作习题

记录PV操作学习过程中的一些习题相关代码

1、读者/写者问题

两组并发进程:读者/写者,共享一个文件F:

  • 多个读者可以同读【允许同读】
  • 只允许一个写者写文件【同写互斥】
  • 写者写时不能被读者读【读写互斥】
  • 写者写之前应该让已有读者写者都退出
读者优先

用wmutex来限制写者,使读者优先

semaphore rmutex=1,wmutex=1;
int readcount=1;

cobegin
    process Reader_i(){
    	while(true){
        	P(rmutex);
            if(readcount==0)P(wmutex)
            readcount++;
            V(rmutex);
            {读文件}
            P(rmutex);
            readcount--;
            if(readcount==0)V(wmutex);
            V(rmutex);
        }
    }
    process Writer_i(){
    	while(true){
            P(wmutex);
            {写文件}
            V(wmutex);
        }
    }
coend
写者优先

用rmutex来限制读者,使写者优先

semaphore rmutex=1,wmutex=1;
semaphore x=1,y=1,z=1;
int readcount=0,writecount=0;

cobegin
    process Reader_i(){
        while(true){
            P(z);
            P(rmutex);
            P(x);
            if(readcount==0)P(wmutex);
            readcount++;
            V(x);
            V(rmutex);
            V(z);
            {读文件}
            P(x);
            readcount--;
            if(readcount==0)V(wmutex);
            V(x);
        }
    }
    process Writer_i(){
        while(true){
            P(y);
            if(writecount==0)P(rmutex);
            writecount++;
            V(y);
            P(wmutex);
            {写文件}
            V(wmutex);
            P(y);
            writecount--;
            if(writecount==0)V(rmutex);
            V(y);
        }
    }
coend
读写公平

用公共信号量S来使读写公平

semaphore rmutex=1,wmutex=1,s=1;
int readcount=0;

cobegin
    process Reader_i(){
        while(true){
            P(s);
            P(rmutex);
            if(readcount==0)P(wmutex);
            readcount++;
            V(rmutex);
            {读文件}
            P(rmutex);
            readcount--;
            if(readcount==0)V(wmutex);
            V(rmutex);
            V(s);
        }
    }
    process Writer_i(){
        while(true){
            P(s);
            P(wmutex);
            {写文件}
            V(wmutex);
            V(s);
        }
    }
coend

2、睡眠的理发师问题

一位理发师、一把理发椅、n把等候区

  • 如果没有顾客,理发师就休眠
  • 顾客到来需要唤醒理发师
  • 如果理发师正在理发时来了顾客,就在等待区等待,等待区满则直接离开
  • 不是互斥型问题,而是协作型问题

【用customers来限制理发师进程,用barbers来限制顾客进程,协作同步】

semaphore customers=0,barbers=0,mutex=1;
int waiting=0,chairs=n;

cobegin
    process Barber(){		//理发师需要一直提供服务,所以需要无限循环
        while(true){
            P(customers);	//是否有顾客,若无则进入休眠(信号量<0)
            P(mutex);		//有顾客,进入操作处理临界区
            waiting--;		//让一个等待的顾客过来理发
            V(barbers);		//理发师被唤醒了,释放一个可理发资源
            V(mutex);		//退出操作处理临界区,下面正式开始理发
            {理发师理发}
        }
    }
    process Customer(){			//顾客只接受一次服务,所以不需要无限循环
    	P(mutex);			//进入操作处理临界区
        if(waiter<chair){	//判断等待区是否还有位置
        	waiting++;		//等待人数
        	V(customers);	//顾客资源数++,并唤醒休眠中的理发师
        	V(mutex);		//退出操作处理临界区
        	P(barbers);		//请求一个理发师资源,如果barbers<0,则先到等待区等待一下
        	{被理发师理发}
        }
        else{
        	V(mutex);		//等待区满,顾客直接离开
        }
    }
coend

3、农夫猎人问题/苹果橘子问题

一个笼子,只能放一个老虎或羊,动物园或饭店从中取对应的动物;
一个盘子,只能放入一个苹果或橘子,爸爸妈妈分别取苹果和橘子;
【两组生产者和消费者共同使用一个缓冲区】

semaphore sput=1,sget[2]={0,0};

cobegin
    process Product_i(int i){
        while(true){
            P(sput);
            {放产物}
            V(sget[i]);
        }
    }
    process Consumer_i(int i){
        while(true){
            P(sget[i]);
            {取产物}
            V(sput);
        }
    }
coend

4、银行业务问题

  • n个储蓄员,足够多的顾客,足够多的等待区
  • 顾客到来先取号,然后等待叫号
  • 每当有储蓄员空闲下来就叫下一个号
semaphore customer=0,server=n.mutex=1;

cobegin
    process Customer(){		//每个顾客只来一次,所以顾客进程不需要无线循环
        P(mutex);
        {取号并在等待区坐下}
        V(mutex);
        V(customer);
        P(sever);
        {接受服务};
    }
    process Server_i(){			//储蓄员需要不断提供服务,所以需要无线循环
        while(true){
            P(customer);
            P(mutex);
            {向顾客叫号,被叫到顾客离开等待区}
            V(mutex)
            {为顾客提供服务}
            V(server);
        }
    }
coend

5、缓冲区管理

  • n个输入进程Pi将字符逐个输入容量为80的缓冲区中
  • 缓冲区满后,输出进程Q一次性取走80个字符
semaphore empty=80,full=0,mutex=1;
char buffer[80];
int count=0,inptr=0;

cobegin
    process P_i(){
        while(true){
            P(empty);
            p(mutex);
            {写入字符到buffer[inptr]}
            count++;
            inptr=(inptr+1)%80;
            if(count==80){
                count=0;
                V(mutex);
                V(full);
            }
            else V(mutex);
        }
    }
    process Q(){
        while(true){
            P(full);
            P(mutex);
            {读取80个字符}
            V(mutex);
            for(int i=0;i<80;i++){
                V(empty);
            }
        }
    }
coend

6、售票问题

汽车司机和售票员之间协同工作:

  • 售票员关好门并通知司机开车,然后售票员售票【关门通知司机】
  • 司机停车后通知售票员才能开门上下客【停车通知售票员】
  • 一名司机,两名售票员,从始发站开始
semaphore run[2]={0,0},stop[2]={0,0};

cobegin
    process Driver(){
        while(true){
            P(run[0]);
            P(run[1]);
            {开车}
            {停车}
            V(stop)
        }
    }
    process Saler_i(int i){
        while(true){
            {上客}
            {关车门}
            V(run[i]);
            {售票}
            P(stop[i]);
            {开车门}
            {下客}
        }
    }
coend

7、吸烟者问题

三个吸烟者+一个供应者,每个吸烟者有一种特别的材料,每次供应者会放两种材料出来,如果跟自己的都不一样,就轮到对应的吸烟者吸烟了

  • 供应者随机放两种材料
  • 吸烟完毕后唤醒供应者
semaphore producter=1,smoker[3]={0,0,0};

cobegin
process Product(){
	while(true){
    	P(producter);
        {随机放两种材料,假设放的材料对应的可吸烟者是i}
        V(smoker[i]);
    }
}
process Smoker_i(int i){
	while(true){
    	P(smoker[i]);
        {吸烟}
        V(producter);
    }
}

8、独木桥问题

有一根独木桥,来自东西两个方向的汽车要通过桥

一边全过完再换边【不公平】

只有一方的车全部过完之后才允许另一方的车过桥,不公平

semaphore wait=1,mutexleft=1,mutexright=1;		//使用wait来饿死另一边
int countleft=0,countright=0;

cobegin
    process CarLeft(){		//每辆车都调用CarLeft函数即可,所以不需要无限循环
        P(mutexleft);
        if(countleft==0)P(wait);
        countleft++;
        V(mutexleft);
        {过桥}
        P(mutexleft);
        countleft--;
        if(countleft==0)V(wait);
        V(mutexleft);
    }
    process CarRight(){		//每辆车都调用CarRight函数即可,所以不需要无限循环
        P(mutexright);
        if(countright==0)P(wait);
        countright++;
        V(mutexright);
        {过桥}
        P(mutexright);
        countright--;
        if(countright==0)V(wait);
        V(mutexright);
    }
coend
限制最大同时通过车辆数【不公平】

在上述不公平情况下,限制同时通过桥的车辆数量为k

semaphore wait=1,mutexleft=1,mutexright=1,maxpass=k;
int countleft=0,countright=0;

cobegin
    process CarLeft(){		//每辆车都调用CarLeft函数即可,所以不需要无限循环
        P(mutexleft);
        if(countleft==0)P(wait);
        countleft++;
        V(mutexleft);
        P(maxpass);			//对同时最大通过数量加以限制
        {过桥}
        V(maxpass);
        P(mutexleft);
        countleft--;
        if(countleft==0)V(wait);
        V(mutexleft);
    }
    process CarRight(){		//每辆车都调用CarRight函数即可,所以不需要无限循环
        P(mutexright);
        if(countright==0)P(wait);
        countright++;
        V(mutexright);
        P(maxpass);			//对同时最大通过数量加以限制
        {过桥}
        V(maxpass);
        P(mutexright);
        countright--;
        if(countright==0)V(wait);
        V(mutexright);
    }
coend
以组单位交替运行【公平】

在第一种的基础上,要求保证以k辆为一组为单位交替运行

semaphore wait=1,mutexleft=1,mutexright=1;		//使用wait来饿死另一边
int countleftup=0,countleftdownp=0,countrightup=0,countrightdown=0;

cobegin
    process CarLeft(){		//每辆车都调用CarLeft函数即可,所以不需要无限循环
        P(mutexleft);
        if(countleftup==0)P(wait);
        countleftup++;
        V(mutexleft);
        {过桥}
        P(mutexleft);
        countleftup--; countleftdown--;
        if(countleftup==0 && countleftdown==k){
        	countleftdown=0;
            V(wait);
        }
        V(mutexleft);
    }
    process CarRight(){		//每辆车都调用CarRight函数即可,所以不需要无限循环
        P(mutexright);
        if(countrightup==0)P(wait);
        countrightup++;
        V(mutexright);
        {过桥}
        P(mutexright);
        countrightup--; countrightdown++;
        if(countrightup==0 && countrightdown==k){
            countrightdown=0;
            V(wait);
        }
        V(mutexright);
    }
coend
类读写公平【公平】

当另一方提出过桥时,应当能阻止当前方的后继车辆,保证公平

semaphore stop=1,wait=1,mutexleft=1,mutexright=1;		//增加stop全局信号量来实现公平
int countleft=0,countright=0;

cobegin
    process CarLeft(){		//每辆车都调用CarLeft函数即可,所以不需要无限循环
        P(stop);
        P(mutexleft);
        if(countleft==0)P(wait);
        countleft++;
        V(mutexleft);
        {过桥}
        P(mutexleft);
        countleft--;
        if(countleft==0)V(wait);
        V(mutexleft);
        V(stop);
    }
    process CarRight(){		//每辆车都调用CarRight函数即可,所以不需要无限循环
        P(stop);
        P(mutexright);
        if(countright==0)P(wait);
        countright++;
        V(mutexright);
        {过桥}
        P(mutexright);
        countright--;
        if(countright==0)V(wait);
        V(mutexright);
        V(stop);
    }
coend
  • 0
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值