PV操作经典问题包括:读者写者问题,生产者消费者问题,哲学家就餐问题,理发师问题。
下面先给出解题通用步骤,再对每一类问题做例题分析,并给出每类问题的特解。

一 PV操作思考通用步骤:

1.有几类进程?每类进程对应一个函数。

生产者1进程对应producer1()
消费者1进程对应consumer1()
消费者2进程对应consumer2()
2.在函数内部用中文描述动作,并在草纸上行间留白供后续使用,并根据这些动作是否重复进行,决定是否加while(1)

    producer{while(1){生产一件商品;把商品放到货架;}}

3.在每个动作之前,思考是否需要P什么?如果需要P操作,写出P操作,并写出对应的V操作(V操作可能在另一进程内)

    producer{while(1){//不需要P生产一件商品;//由于需要消耗货架容量,所以需要P(货架空闲区)//货架属于临界资源需要互斥访问,所以P(货架互斥信号量)把商品放到货架;//P的对应V操作:释放临界资源,所以V(货架互斥信号量)//由于货架被放上货物,货物量增加,所以V(货架货物量)

4.写完PV操作后,再完整地定义信号量

    semaphore mutex=1;//临界资源semaphore empty=5//空闲区数量semaphore full=0//货物数量int count=0;//整形信号量,用于统计人数等semaphore CSignal;//在count++ count————时,套上P()V(),实现互斥更改count值

5.完成上述步骤之后进行检查,检查多个P操作连续出现时是否可能出现死锁。一对PV前后出现,不会死锁;连续多个P导致死锁(请求和保持),可尝试调换前后P的顺序。

二生产者消费者问题

例一用于实操一遍通解过程的1,2,3,4,5步,例二用于说明第5步会遇到的问题。

例一:某工厂有两个生产车间和一个装配车间,两个生产车间分别生产 A、B 两种零件,装配车间的任务是把 A、B 两种零件组装成产品。两个生产车间每生产一个零件后,都要分别把它们送到装配车间的货架 F1、F2上。F1 存放零件 A,F2 存放零件 B,F1 和 F2 的容量均可存放 10 个零件。装配工人每次从货架上取一个零件 A 和 一个零件 B 后组装成产品。请用 P、V 操作进行正确管理。

思考步骤,解体流程:
1.有几类进程?每类进程对应一个函数。

生产者A进程对应producerA()
生产者B进程对应producerB()
消费者进程对应consumer()
2.在函数内部用中文描述动作,并在草纸上行间留白供后续使用,并根据这些动作是否重复进行,决定是否加while(1)

    producerA{while(1){生产一件零件A;把零件A放到货架F1;}}producerB{while(1){生产一件零件B;把零件B放到货架F2;}}consumer{while(1){从货架F1取一件零件A;从货架F2取一件零件B;把零件A和B组装;}}

3.在每个动作之前,思考是否需要P什么?如果需要P操作,写出P操作,并写出对应的V操作(V操作可能在另一进程内)

    producerA{while(1){生产一件零件A;P(emptyF1)//由于需要消耗货架容量,所以需要P(货架空闲区)P(mutexF1)//货架属于临界资源需要互斥访问,所以P(货架互斥信号量)把零件A放到货架F1;V(mutexF1);//P的对应V操作:释放临界资源,所以V(货架互斥信号量)V(fullF1)//由于货架被放上货物,货物量增加,所以V(货架货物量)}}producerB{while(1){生产一件零件B;P(emptyF2)//由于需要消耗货架容量,所以需要P(货架空闲区)P(mutexF2)//货架属于临界资源需要互斥访问,所以P(货架互斥信号量)把零件B放到货架F2;V(mutexF2);//P的对应V操作:释放临界资源,所以V(货架互斥信号量)V(fullF2)//由于货架被放上货物,货物量增加,所以V(货架货物量)}}consumer{while(1){P(fullF1)//由于需要消耗货物A,所以需要P(货架货物量)P(mutexF1)//货架属于临界资源需要互斥访问,所以P(货架互斥信号量)从货架F1取一件零件A;V(mutexF1);//P的对应V操作:释放临界资源,所以V(货架互斥信号量)V(emptyF1)//取完货物,货架F1空闲区增加,所以V(货架空闲区)P(fullF2)//由于需要消耗货物B,所以需要P(货架货物量)P(mutexF2)//货架属于临界资源需要互斥访问,所以P(货架互斥信号量)从货架F2取一件零件B;V(mutexF2);//P的对应V操作:释放临界资源,所以V(货架互斥信号量)V(emptyF2)//取完货物,货架F2空闲区增加,所以V(货架空闲区)把零件A和B组装;}}

4.写完PV操作后,再完整地定义信号量

    semaphore mutexF1=1;//临界资源semaphore mutexF2=1;semaphore emptyF1=10;//空闲区数量semaphore emptyF2=10;semaphore full1F=0;//货物数量semaphore full2F=0;

5.完成上述步骤之后进行检查,检查多个P操作连续出现时是否可能出现死锁。一对PV前后出现,不会死锁;连续多个P导致死锁(请求和保持),可尝试调换前后P的顺序。

未发现死锁现象,完整答案:

    semaphore mutexF1=1;//临界资源semaphore mutexF2=1;semaphore emptyF1=10;//空闲区数量semaphore emptyF2=10;semaphore full1F=0;//货物数量semaphore full2F=0;producerA{while(1){生产一件零件A;P(emptyF1)//由于需要消耗货架容量,所以需要P(货架空闲区)P(mutexF1)//货架属于临界资源需要互斥访问,所以P(货架互斥信号量)把零件A放到货架F1;V(mutexF1);//P的对应V操作:释放临界资源,所以V(货架互斥信号量)V(fullF1)//由于货架被放上货物,货物量增加,所以V(货架货物量)}}producerB{while(1){生产一件零件B;P(emptyF2)//由于需要消耗货架容量,所以需要P(货架空闲区)P(mutexF2)//货架属于临界资源需要互斥访问,所以P(货架互斥信号量)把零件B放到货架F2;V(mutexF2);//P的对应V操作:释放临界资源,所以V(货架互斥信号量)V(fullF2)//由于货架被放上货物,货物量增加,所以V(货架货物量)}}consumer{while(1){P(fullF1)//由于需要消耗货物A,所以需要P(货架货物量)P(mutexF1)//货架属于临界资源需要互斥访问,所以P(货架互斥信号量)从货架F1取一件零件A;V(mutexF1);//P的对应V操作:释放临界资源,所以V(货架互斥信号量)V(emptyF1)//取完货物,货架F1空闲区增加,所以V(货架空闲区)P(fullF2)//由于需要消耗货物B,所以需要P(货架货物量)P(mutexF2)//货架属于临界资源需要互斥访问,所以P(货架互斥信号量)从货架F2取一件零件B;V(mutexF2);//P的对应V操作:释放临界资源,所以V(货架互斥信号量)V(emptyF2)//取完货物,货架F2空闲区增加,所以V(货架空闲区)把零件A和B组装;}}

例二:某寺庙有小和尚、老和尚若干,有一水缸,由小和尚提水入缸供老和尚引用。水缸可容 10 桶水,水桶自同一井中。水井径窄,每次只能容一个桶取水。水桶总数为 3 个。每次入缸取水仅为 1 桶水,且不可同时进行。试给出有关从缸取水、入水的算法描述。

先给出正确解答,再说明第5步可能出现的问题。

semaphore well = 1;     //用于互斥地访问水井;
semaphore vat = 1;     //用于互斥的访问水缸;
semaphore empty = 10;  //用于表示水缸中剩余空间;
semaphore full = 0;        //表示水缸中水的桶数;
semaphore pail = 3;        //表示有多少个水桶可以用,初始值为3;// 老和尚
while(1){P(full);P(pail);   P(vat);从水缸中打一桶水;V(vat);V(empty);喝水;V(pail);
}// 小和尚
while(1){P(empty);P(pail);P(well);从井中打一桶水;V(well);P(vat);将水倒入水缸中;V(vat);V(full);V(pail);
}

我们在写P操作时,遇到的多个P操作,应该先写哪个P呢?我给出策略1可以把互斥访问临界资源的P(mutex)放在最后,而前面的多个P可能不确定,假如老和尚写成

 P(pail);//取桶P(full);//确定有水  P(vat);//互斥缸从水缸中打一桶水;

而此时缸中无水,且有3个和尚共取了3个桶,那么小和尚无法取桶去取水,老和尚就永远喝不到水,产生死锁。
这时我们就应该调换P操作顺序为

 P(full);P(pail);    P(vat);从水缸中打一桶水;

那么我们就会产生疑问,有没有一种思考方式来直接避免多个P出现死锁呢?下面我给出一种策略2
如果我们要做两件事,且先做A,再做B,那么我们就应该先确保做B所需资源存在,再确定做A所需资源存在。

比如老和尚要喝水,两件事:先取桶,再从缸里取水,那么我们就应该先确定缸里水存在,再确定桶存在。用PV描述:

 P(full);确定缸里水存在P(pail);确定桶存在

再比如小和尚要取水,两件事:先从用桶从井里取水,再把水倒入缸中空闲区,那么我们就应该先确定缸中空闲区存在,再确定桶存在。用PV描述:

 P(empty);P(pail);

三读者写者问题

对读者优先,读写公平,写者优先三种策略,我们按照通解写出答案,再对特殊部分进行解读。

三.1读者优先

按照通解得到:

semaphore RCsignal=1;//读者数修改互斥
semaphore mutex=1;//临界资源互斥
int count=0;//读者数读者部分:
reader(){while(1){P(mutex);读;V(mutex);}
}写者部分:
writer(){while(1){P(mutex);写;V(mutex);}
}

使用了整形信号量readcount,目的是在第一个读者进入临界资源时,锁住临界资源,使后续读者可以继续访问而后续写者无法访问;在最后一个读者撤出临界资源时,解锁临界资源,使后续读者或写者都可访问。

semaphore RCsignal=1;//读者数修改互斥
semaphore mutex=1;//临界资源互斥
int count=0;//读者数读者部分:
reader(){while(1){P(RCsignal);if(count==0)P(mutex);V(RCsignal);读;P(RCsignal);count--;if(count==0)V(mutex);V(RCsignal);}
}写者部分:
writer(){while(1){P(mutex);写;V(mutex);}
}

三.2读写公平

读写公平分为两种,一种是部分自行抢占部分先来先服务,一种是先来先服务。
两者的PV操作区别是写者中P(rw)的位置不同。
书中,博客中所给的基本都是第一种读写公平,个人认为第二种是更公平的写法。
部分自行抢占,部分先来先服务:写者A在访问临界资源时,又先后来了B,C,那么B,C有同等概率先访问临界资源;读者A在访问临界资源时,又
先后来了B,C,那么B将优先于C先访问临界资源。
部分自行抢占部分先来先服务的具体机制

        部分自行抢占部分先来先服务{目前临界资源正被某读者A访问{若此时先后来到一个读者B,一个写者C{B与A同时读;}若此时先后来到一个写者B,一个读者C{A出后,B写;}目前临界资源正被某写者A访问{若此时先后来到一个读者B,一个写者C{A出后,BC有同等概率抢占临界资源;}若此时先后来到一个写者B,一个读者C{A出后,BC有同等概率抢占临界资源;}}

如何实现这个机制呢?
我们引入一个信号量rw,当A在读时,来B,B即获得下一位进入临界区的资格。所以B(无论时读写)应首先P(rw),获得资格,此时若再来C,则C被P(rw)阻塞,即C无法获得资格。
若B为写,已经获得资格,那么B什么时候再释放这个资格呢?答案是当B写完,B写完后,后续来者自行抢占。
若B为读,已经获得资格,那么B什么时候再释放这个资格呢?答案是当B在读之前,因为读时B已经像A那样允许下一位获得资格。

semaphore mutex=1;
semaphore RCsignal=1;
semaphore rw=1;
int count=0;读者部分:
reader(){while(1){P(rw);P(RCsignal);if(count==0)P(mutex);count++;V(RCsignal);V(rw);读;P(RCsignal);count--;if(count==0)V(mutex);V(RCsignal);}
}写者部分:
writer(){while(1){P(rw);P(mutex);写;V(mutex);V(rw);}
}

先来先服务:简单来说A在访问临界资源时,又先后来了B,C,那么B将优先于C先访问临界资源。
先来先服务的具体机制:

        先来先服务{目前临界资源正被某读者A访问{若此时先后来到一个读者B,一个写者C{B与A同时读;}若此时先后来到一个写者B,一个读者C{A出后,B写;}目前临界资源正被某写者A访问{若此时先后来到一个读者B,一个写者C{A出后,B读;}若此时先后来到一个写者B,一个读者C{A出后,B写;}}

如何实现这个机制呢?
我们引入一个信号量rw,当A在读或写时,来B,B即获得下一位进入临界区的资格。所以B(无论时读写)应首先P(rw),获得资格,此时若再来C,则C被P(rw)阻塞,即C无法获得资格。
B已经获得资格,那么B什么时候再释放这个资格呢?答案是当B在读写之前,因为读写时B已经像A那样允许下一位获得资格。

semaphore mutex=1;
semaphore RCsignal=1;
semaphore rw=1;
int count=0;读者部分:
reader(){while(1){P(rw);P(RCsignal);if(count==0)P(mutex);count++;V(RCsignal);V(rw);读;P(RCsignal);count--;if(count==0)V(mutex);V(RCsignal);}
}写者部分:
writer(){while(1){P(rw);P(mutex);V(rw);写;V(mutex);}
}

三.3写者优先

写者优先的规则:
1.读者与写者,写者与写者不能同时访问缓冲区;
2.无写进程时,各读者可同时访问缓冲区;
3.读者和写者都等待时,写者优先访问缓冲区;

“读者和写者都等待时,写者优先访问缓冲区”解读
读者写者都等待的情况,即有写者正在访问临界资源,而不可能是有读者正在访问临界资源,这是因为有读者在访问临界资源时,后到的写者 只能等待访问临界资源的读者撤出后 才能访问临界资源(读者写者问题的基本原则),而后到的读者可以与前面的读者共同访问临界资源。

写优先代码解读
在读者写者都等待的情况,即有写者正在访问临界资源时,write=0(代码中写了,当访问临界资源的写者撤出时,Wcount=0,才会V(write),使write=0),假如此时按时间顺序又来了读者A,写者B。此时在write=0的情况下,按时间顺序读者A先执行P(write),即读者A被阻塞;然后按时间顺序写者B执行,由于此时Wcount=1,即P(write)语句不会执行,即不会在此阻塞,继续执行直到P(mutex)被阻塞。目前读者A与写者B都处于阻塞状态。但一旦正在访问临界资源的写者退出并执行V(mutex)后,使得mutex=1,并且写者B得知mutex=1,并执行P(mutex),进而进行“写”。A退出时,Wcount=1,因此不会V(write),因此读者B将继续被阻塞。
此时即实现了,在读者写者都等待时,即有写者正在访问临界资源的情况下,按时间顺序又来了读者A,一个写者B,而执行结果就是,读者A被阻塞,写者B也被阻塞。但一旦正在访问临界资源的写者退出并执行V(mutex)后,写者B进行“写”,即写者B先于读者A,实现了插队。即读者和写者都等待时,写者优先访问缓冲区。

semaphore write=1;//进程优先互斥
semaphore mutex=1;//临界资源互斥
semaphore RCsignal=1;//读者数Rcount修改互斥
semaphore WCsignal=1;//写者数Wcount修改互斥
int Rcount=0;//读者数
int Wcount=0;//写者数读者部分:
reader(){while(1){P(write);P(RCsignal);if(Rcount==0)P(mutex);Rcount++;V(RCsignal);V(write);读;P(RCsignal);Rcount--;if(Rcount==0)V(mutex);V(RCsignal);}
}写者部分:
writer(){while(1){P(WCsignal);if(WCsignal==0)P(write);Wcount++;V(WCsignal);P(mutex);写;V(mutex);P(WCsignal);Wcount--;if(Wcount==0)V(write);V(WCsignal);}
}

四哲学家进餐问题

哲学家进餐问题的特点是只有一类进程,且进程数量小于资源数量。
解决方法是当一个进程能够得到所有需要的资源时,再一次性取走这些资源。
通解:

    process(){while(1){P(mutex);//用于互斥访问资源    if(资源A>=a&&资源B>=b){//如果所有资源都足够资源A--;//一次性获得全部资源资源B--;V(mutex);break;//已经获得资源,跳出循环,至做事}    elseV(mutex); //资源不够,重复查询}做事;//比如哲学家吃饭P(mutex);//互斥访问资源资源A++;//一次性退还全部资源资源B++;V(mutex); }

五理发师问题

实在复杂,这里跳向一篇好文。
链接: https://blog.csdn.net/duanzhengbing/article/details/52141699

PV操作经典问题通解相关推荐

  1. PV操作经典例题——吃水果

    例1:桌上有一个盘子,每次只能放一个水果,妈妈向盘中放苹果和橘子,儿子专等吃盘里的橘子,女儿专等吃盘里的苹果.只要盘子空,妈妈可向盘中放水果,仅当盘中有自己需要的水果时,儿子或女儿可从中取出,请给出他 ...

  2. 【操作系统】PV 操作经典例题---三个进程之间的同步

    问题: 总共有 读入.执行.打印 三个进程,试用PV操作描述读入B1打印B2的同步过程. 问题解读: 这个问题就是说了这样一件事:一个输入B1,被操作之后,成为B2,将B2打印.怎样用PV操作来说这件 ...

  3. PV 操作经典例题---三个进程之间的同步

    问题: 总共有 读入.执行.打印 三个进程,试用PV操作描述读入B1打印B2的同步过程. 问题解读: 这个问题就是说了这样一件事:一个输入B1,被操作之后,成为B2,将B2打印.怎样用PV操作来说这件 ...

  4. PV操作经典例题——哲学家进餐问题

    哲学家进餐问题: 五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在桌子上有五只碗和五只筷子,他们的生活方式是交替地进行思考和进餐.平时,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的筷子,只 ...

  5. PV操作经典例题——司机与售票员的进程同步问题

    例1: 司机的活动: 启动车辆, 正常行车, 到站停车. 售票员活动: 关车门, 售票, 开车门. 注意:当发车时间到,售票员关好车门后,司机才能启动车辆,售票员才开始售票. 当到站时,司机停稳车后, ...

  6. PV操作经典例题——银行业务办理问题

    例:某银行提供1个服务窗口和10个供顾客等待的座位,顾客到达银行时,若有空座位,则到取号机上领取一个号,等待叫号.取号机每次仅允许一位顾客使用,当营业员空闲时,通过叫号选取一位顾客,并为其服务. 解析 ...

  7. java实现的PV操作经典例子:读者写者、贪睡的理发师、生产者消费者。

    其中读者写者和贪睡的理发师使用的Semaphore类:生产者消费者使用的是管程. 读者写者 class Semaphore {int value;public Semaphore(int v){thi ...

  8. 几个java实现的PV操作经典例子:读者写者、贪睡的理发师、生产者消费者

    其中读者写者和贪睡的理发师使用的Semaphore类:生产者消费者使用的是管程. 读者写者: class Semaphore {int value;public Semaphore(int v){th ...

  9. 操作系统 | PV操作七大经典问题 生产者消费者 读者写者 哲学家进餐 理发师理发睡觉 和尚打水 吸烟者 吃水果

    一.生产者消费者问题 生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案 ...

  10. 【操作系统】经典PV操作题目

    5个经典PV操作题(附答案) 三个进程之间的同步 pv操作的经典习题 PV操作题型整理 生产者和消费者 生产者消费者问题 当只有一个生产者和一个消费者的时候,且只有一个缓冲区 要考虑生产者和消费者两个 ...

最新文章

  1. 【ACM】杭电OJ 2018
  2. Python-PyCharm 报错解决:ImportError: cannot import name 'InteractiveConsole' from 'code'
  3. Cloud一分钟 | 马云发表致股东的公开信;5G算什么?中国已着手研究6G相关工作...
  4. 酷睿i7cpu适合的linux,CPU性能篇 - Core i7-4770K Linux之旅:有喜有忧_Linux新闻_Linux公社-Linux系统门户网站...
  5. LTE物理传输资源(2)-频带、信道带宽和频点号EARFCN
  6. dos.ORM配置和使用
  7. windows自动导出oracle数据库,Oracle数据库的自动导出备份脚本(windows环境)
  8. 编译OpenJDK8:NMAKE : fatal error U1077
  9. C++ string append方法的常用用法
  10. oracle系统卸载干净,完全卸载oracle|oracle卸载|彻底卸载oracle
  11. css inset属性
  12. 工具使用,PS隐藏技能—对称绘画
  13. 每天学一个 Linux 命令:dnf
  14. 军团要塞2正版服务器,Team Fortress 2
  15. layui js 自定义打印功能实现
  16. js循环绑定事件问题及解决方法
  17. 【均衡器】LS均衡器,DEF均衡器以及LMMSE均衡器的误码率性能对比仿真
  18. 教你轻松用Python画一只肥肥的柯基狗狗——turtle库绘制椭圆与弧线实践
  19. ABBYY FineReader PDF15下载安装教程
  20. 基于MATLAB的图像压缩感知

热门文章

  1. 租房申请html模板,实用的租房房源标题模板
  2. Rasa3 domain官方文档翻译
  3. matlab 数字显示完整,如何在matlab中同时显示字符串和数字?
  4. Win10锁屏之后屏幕自动关闭怎么办
  5. 用C语言画空心三角形
  6. kero入门学习总结
  7. 原型工具axure7.0
  8. mac java报内存不足_苹果电脑显示内存不足怎么办_mac提示内存不足的解决方法-系统城...
  9. Vijos 3764 牛奶题
  10. prosody之component