【408精华知识】PV大题最全总结!

在这里插入图片描述

PV大题可以分为以下几类:生产者-消费者问题、吸烟者问题、理发师问题、读写者问题、哲学家就餐问题。其中吸烟者问题、理发师问题本质也是生产者-消费者问题。所以本文将从生产者-消费者问题、读写者问题、哲学家就餐问题三个问题出发,讲解PV大题的解题办法。

零、基本书写步骤

  1. 先写函数
  2. 写个循环
  3. 写下动作
  4. 放置P V (用P减V加操作信号量以实现同步互斥)
  5. 定义信号

接下来我们以生-消问题为例子来讲解这个书写步骤。

一、生产者-消费者问题

题目:A、B、C三个工人,A生产a产品,然后放在F1货架上(初始m空位);B生产b产品,然后放在F2货架上(初始n空位);C用a、b产品组装c。请用信号量机制表示这三个进程的同步与互斥活动。

生产者-消费者问题可以很好地诠释PV两个信号量的含义,生产代表增加,也就是V的含义,消费代表减少,也就是P的含义。

  1. 先写函数,这里有A、B、C三个函数。
A(){
}

B(){
}

C(){
}
  1. 写个循环,循环表示这三个函数可以一直工作。
A(){
	while(1){
	}
}

B(){
	while(1){
	}
}

C(){
	while(1){
	}
}
  1. 写下动作,表示三个函数各自执行的任务。
A(){
	while(1){
		生产A;
		把A放在F1货架上;
	}
}

B(){
	while(1){
		生产B;
		把B放在F1货架上;
	}
}

C(){
	while(1){
		从F1上拿A;
		从F2上拿B;
		组装c;
	}
}
  1. 放置P V (P表示资源+1,V表示资源-1),设置同步、互斥信号量,注意各种动作对于资源量的影响,以及资源是否要互斥访问。在放置PV时,有两大原则:
    (1)P在动作前,V在动作后,对于同步信号量,先固定V的位置,再固定P的位置;
    (2)负责互斥的信号量永远放在最里层。
A(){
	while(1){
		生产A;
		P(F1);
		P(mutex_F1);
		把A放在F1货架上;
		V(mutex_F1);
		V(A);
	}
}

B(){
	while(1){
		生产B;
		P(F2);
		P(mutex_F2);
		把B放在F2货架上;
		V(mutex_F2);
		V(B);
	}
}

C(){
	while(1){
		P(A);
		P(mutex_F1);
		从F1上拿A;
		V(mutex_F1);
		V(F1);
		P(B);
		P(mutex_F2);
		从F2上拿B;
		V(mutex_F2);
		V(F2);
		组装c;
	}
}
  1. 定义信号,先根据资源量和动作设定信号,最后再对信号量进行定义,这样可以更加清晰。
semaphore mutex_F1=mutex_F2=1; //互斥访问两个货架
semaphore A=B=0; //A、B资源数量
semaphore F1=m; //F1初始空位
semaphore F2=n; //F2初始空位

故完整伪代码如下:

semaphore mutex_F1=mutex_F2=1; //互斥访问两个货架
semaphore A=B=0; //A、B资源数量
semaphore F1=m; //F1初始空位
semaphore F2=n; //F2初始空位

A(){
	while(1){
		生产A;
		P(F1);
		P(mutex_F1);
		把A放在F1货架上;
		V(mutex_F1);
		V(A);
	}
}

B(){
	while(1){
		生产B;
		P(F2);
		P(mutex_F2);
		把B放在F2货架上;
		V(mutex_F2);
		V(B);
	}
}

C(){
	while(1){
		P(A);
		P(mutex_F1);
		从F1上拿A;
		V(mutex_F1);
		V(F1);
		P(B);
		P(mutex_F2);
		从F2上拿B;
		V(mutex_F2);
		V(F2);
		组装c;
	}
}

二、读写者问题

题目:有读者和写者两组并发进程,共享一个文件,当两个或以上的读进程同时访问共享数据时不会产生副作用,但若某个写进程和其他进程(读进程或写进程)同时访问共享数据时则可能导致数据不一致的错误。因此要求:①允许多个读者可以同时对文件执行读操作:②只允许一个写者往文件中写信息;③任意一个写者在完成写操作之前不允许其他读者或写者工作;④写者执行写操作前,应让已有的读者和写者全部退出。请用信号量机制表示进程之间的同步与互斥活动

读写者问题可总结为:读读可并行,读写、写写不可并行。有三种方式:读优先、写优先和读写公平法,下面我们来依次讲解。

读优先:

int count=0;  //用于记录当前的读者数量
semaphore mutex=1;  //用于保护更新count变量时的互斥
semaphore rw=1;  //用于保证读者和写者互斥地访问文件

Writer(){
	while(1){
		P(rw);
		写;
		V(rw);
	}
}

Reader(){
	while(1){
		P(mutex);
		if(count == 0){
			P(rw);
		}
		count++;
		V(mutex);
		读;
		P(mutex);
		count--;
		if(count == 0){
			V(rw);
		}
		V(mutex);
	}
}

写优先:

由于只有最后一个读进程离开后,rw信号量才会被还原,这导致了读优先,而读优先会导致写进程被饿死,若希望写进程优先,即当有读进程正在读共享文件时,有写进程请求访问,这时应禁止后续读进程的请求,等到已在共享文件的读进程执行完毕,立即让写进程执行,只有在无写进程执行的情况下才允许读进程再次运行。为此,增加一个信号量保证写优先。

int count=0;  //用于记录当前的读者数量
semaphore mutex=1;  //用于保护更新count变量时的互斥
semaphore rw=1;  //用于保证读者和写者互斥地访问文件

Writer(){
	while(1){
		P(w);
		P(rw);
		写;
		V(rw);
		V(w);
	}
}

Reader(){
	while(1){
		P(w);
		P(mutex);
		if(count == 0){
			P(rw);
		}
		count++;
		V(mutex);
		V(w);
		读;
		P(mutex);
		count--;
		if(count == 0){
			V(rw);
		}
		V(mutex);
	}
}

读写公平:

若想要实现读写公平法,只需要在写优先的基础上,将写者进程的V(w)放到P(rw)之后即可。

int count=0;  //用于记录当前的读者数量
semaphore mutex=1;  //用于保护更新count变量时的互斥
semaphore rw=1;  //用于保证读者和写者互斥地访问文件

Writer(){
	while(1){
		P(w);
		P(rw);
		V(w);
		写;
		V(rw);
	}
}

Reader(){
	while(1){
		P(w);
		P(mutex);
		if(count == 0){
			P(rw);
		}
		count++;
		V(mutex);
		V(w);
		读;
		P(mutex);
		count--;
		if(count == 0){
			V(rw);
		}
		V(mutex);
	}
}

三、哲学家就餐问题

题目:一张圆桌边上坐着n个哲学家,每两名哲学家之间的桌上摆一根筷子,两根筷子中间是一碗米饭。哲学家们倾注毕生精力用于思考和进餐,哲学家在思考时,并不影响他人。只有当哲学家饥饿时,才试图拿起左、右两根筷子(一根一根地拿起)。若筷子己在他人手上,则需要等待。饥饿的哲学家只有同时拿到了两根筷子才可以开始进餐,进餐完毕后,放下筷子继续思考。请用信号量机制表示进程之间的同步与互斥活动

哲学家就餐问题的根本解决办法是设置mutex信号量为不会发生死锁的最高数n,且要一次性拿完所有所需要的资源,也就是说只允许最多n个进程同时开始拿资源。

semaphore mutex = n-1; //n为不会发生死锁的最高数目
semaphore lkuai[n] = rkuai[n] = {1};  //左右筷子值都初始化为1

Eat_i(){ //第i个哲学家进程
	while(1){
		P(mutex);
		P(lkuai[i]);
		拿左筷子;
		P(rkuai[i]);
		拿右筷子;
		V(mutex);
		吃饭;
		V(lkuai[i]);
		放下左筷子;
		V(rkuai[i]);
		放下右筷子;
		思考;
	}
}

最后,其实PV大题很简单,总结一句话就是用P减V加操作信号量以实现同步互斥

写在后面

这个专栏主要是我在学习408真题的过程中总结的一些笔记,因为我学的也很一般,如果有错误和不足之处,还望大家在评论区指出。希望能给大家的学习带来一点帮助,共同进步!!!

参考资料
[1]王道408教材(2025版)
[2]王道课程资料

  • 23
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值