哲学家进餐问题实验报告_操作系统复习笔记(王道)C2.3经典同步问题

这一部分比较重要,理解的地方比较多,单独写一篇。


一、生产者消费者问题

一组生产者进程和一组消费者进程共享有限缓冲区,一个生产一个消费。

只有缓冲区有空时生产者才能生产放入。

只有缓冲区有产品的时候消费者才能消费。

而且缓冲区属于临界资源,同一时间只能一个进程操作。

举个简单的栗子:

先简单粗暴理解一下pv操作,p是等着,有值我才上(s>=0)。v操作是资源++。

semaphore mutex=1;//柜台钥匙(临界区互斥信号量)
semaphore empty=n;//柜台空位(空闲缓冲区)
semaphore full=0;//小熊饼干数量(缓冲区初始化为空)

producer(){
while(1){
produce an item in nextp;//生产一个小熊饼干
p(empty);//看一眼柜台,柜台有空位了我就放进去
p(mutex);//钥匙在这儿我就拿过来打开柜台
add nextp to buffer;//小熊饼干放进去
v(mutex);//关上柜台把钥匙放回去
v(full);//告诉别人小熊饼干多了一个
}
}

consumer(){
while(1){
p(full);//看一眼柜台,有小熊饼干
p(mutex);//看看钥匙在不在,在我就去拿了
remove an item from buffer;//拿走一个小熊饼干
v(mutex);//钥匙放回去
v(empty);//告诉老板柜台空位多了一个你赶紧去做
comsume the item;//吃掉这个小熊饼干
}
}

里面所有的先瞧上一眼,都对应着p操作的死等判断,while循环。

举个复杂的栗子:

7f05daa06feceb1b7829ba345e2921b2.png
稍微复杂的一个模型
semaphore plate=1,apple=0,orange=0;
dad(){
while(1){
prepare an apple;
p(plate);
put the apple on the plate;
v(apple);
}
}

mom(){
while(1){
prepare an orange;
p(plate);
put the orange on the plate;
v(orange);
}
}

son(){
while(1){
p(orange);
take an orange from the plate;
v(plate);
eat the orange;
}
}

son(){
while(1){
p(apple);
take an apple from the plate;
v(plate);
eat the apple;
}
}

其实和前一个栗子差不多,这里要判断一下是不是自己想要的,而且只有一个盘子,必须有人拿走水果释放盘子才能继续往里放入。


二、读者-写者问题

读者和写者两组并发进程,允许多个读者同时读,但是一旦有一个进程开始写,直到写完成之前都不允许其他进程读和写。

1.读者优先算法

int count=0;//记录当前的读者数量
semaphore mutex=1;//count变量的锁
semaphore rw=1;//读写区的锁

writer(){
while(1){
p(rw);//没有人在读和写的时候,上锁
writing;写
v(rw);//开锁
}
}

reader(){
while(1)
p(mutex);//没有人再修改count变量的时候,上锁
if(count==0) p(rw);//如果我是第一个读者,给区域上锁防止有进程来写
count++;读者+1
v(mutex);给count变量开锁
reading;读
p(mutex);给count上锁
count--;读者-1
if(count==0) v(rw);如果我是最后一个读者,给区域开锁
v(mutex);给count变量开锁
}
}

这样做的坏处是,只要有读进程活跃,写进程就会一直等待。如果陆续有读进程在读,则写进程可能因为等待时间太长而饿死。

2.写者优先算法

int cout=0;
semaphore mutex=0;
semaphore rw=1;
semaphore w=1;

writer(){
while(1){
p(w);//没人写的时候锁定
p(rw);//没人读的时候锁定
writing;
v(rw);
v(w);
}
}

reader(){
while(1){
p(w);没人要写的时候锁定
p(mutex);
if(count==0) p(rw);加锁防止进程写
count++;
v(mutex);
v(w);
reading;
p(mutex);
count--;
if(count==0) v(rw);
v(mutex);
}
}

这个相对于第一个算法的不同的是,第一个算法没有写申明,写者只有死等没有人读的时候才会进来写,读者读之前也不会询问有没有人将要写,反正此时没有人写我就进来读。所以写进程一旦没有区域的控制权就只能傻等所有的读进程都读完。这一个算法就在写进程前加了个声明,在我真正获得区域的控制权之前先告诉大家我想要写,每个读进程读之前也会看看有没有进程想写,有的话读进程就会等待,这时只要现在正在读的进程执行完毕,写进程就可以获得区域的控制权,新的读进程只能等待下一次区域被释放。

第二个算法其实不是完全写者优先,他叫读写公平算法,只是相对于算法一而言,写进程地位要高一点,可以不用傻等所有读进程。真正的写优先王道没讲,我也暂时不看了。


三、哲学家进餐问题

510b71927cbbb76c4394f8add5cd2456.png

要拿起了两边的筷子才能进餐。

semaphore chopstick[5]={1,1,1,1,1};
pi(){
do{
p(chopstick[i]);
p(chopstick[(i+1)%5]);
eat;
v(chopstick[i]);
v(chopstick[(i+1)%5]);
think;
}while(1);
}

这个算法存在一个问题,如果大家同时拿起了左边的筷子,那么每一个人都陷入了死等状态。

正确的规则如下:

仅当一个哲学家左右两边的筷子都可用的时候才允许他去抓筷子。

semaphore chopstick[5]={1,1,1,1,1}
semaphore mutex=1;
pi(){
do{
p(mutex);//获得互斥量再取筷子,取就取走一了双再允许别人进行取操作
p(chopstick[i]);
p(chopstick[(i+1)%5]);
v(mutex);
eat;
v(chopstick[i]);
v(chopstick[(i+1)%5]);
thinck;
}while(1);
}

四、吸烟者问题

假设一个系统有三个抽烟者进程和一个供应者进程。

供应者供应三种材料:烟草,纸,和胶水。抽烟者只有拿到了这三种材料之后才可以吸烟。

一个抽烟者有烟草,一个有纸,另一个有胶水。供应者每次只将两种材料放到桌子上,拥有剩下那一种材料的抽烟者可以拿走材料并且抽掉它,并且给供应者一个信号告诉已经完成。然后供应者才会继续往上放另外两种材料。

int random;
semaphore leafAndPaper;
semaphore leafAndGlue;
semaphore paperAndGlue;
semaphore finish;

process producer(){
while(1){
random=任意整数;
random=random%3;
if(random==0) v(leafAndPaper);
else if(random==1) v(leafAndGlue);
else v(paperAndGlue);
放在桌子上;
p(finish);//等他们抽掉
}
}

process c1(){
while(1){
p(leafAndPaper);
卷烟抽掉;
v(finish);
}
}

process c2(){
while(1){
p(leafAndGlue);
卷烟抽掉;
v(finish);
}
}

process c3(){
while(1){
p(paperAndGlue);
卷烟抽掉;
v(finish);
}
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值