PV_Summary

PV操作

  1. 观察者和报告者是两个并发执行的进程。
    观察者不断观察并对通过的卡车计数;
    报告者不停地将观察者的计数打印,并归零。
    请用P、V原语进行正确描述。
int count=0;
Semaphore mutex=1;
Observer:				Reporter:					Main():
	while(true):			while(true):				parbegin
		P(mutex):				P(mutex)					Observer();
            						打印count;			   Rporter();
			count++;				count=0;			parend
		V(mutex);				V(mutex)

  1. 图书馆问题:图书馆有N个座位,一张登记表,要求:
    读者进入时需先登记,取得座位号;
    出来时注销
    用P、V原语描述读者的使用过程。

    Semaphore count=N;
    Semaphore mutex=1;
            
    Main():
    	parbegin:
    		In();
    		阅读;
    		Out();
    	parend
            
    In():
    while(true):
    	P(count):
    		P(mutex):
    			登记;
    		V(mutex);
    		
    Out():
    while(true):
    	P(mutex):
    		注销
    	V(mutex);
    	V(count);
           
    
    
  2. 公交车场景

在这里插入图片描述

Semophore door=0//是否允许售票员开门
Semophore car=0//是否允许司机启动汽车
Main():
	Driver();
	Conductor();

Driver():
while:
	P(car):
		启动;
        运行;
        停车;
        V(door);

Conductor():
while(true):
	关车门;
    V(car);
	售票;
	P(door):
		开车门;
  1. 生产者与消费者问题:生产者:满则等待,空则填充
    消费者:空则等待,有则获取
    不允许同时进入缓冲区

    先拿资源再拿锁

    1. 无限缓冲
semaphore num=0;
semaphore mutex=1;

Producer:
while(true):
	生产;
	P(mutex):
		填充buffer;
	V(mutex);
	V(num);

Consumer:
while(true):
	P(num):
		P(mutex);
			消费buffer;
		V(mutex);
		消费;
          
  1. 有限缓冲
semaphore full=0;//满 缓冲区数量
semaphore empty=N;//空 缓冲区数量
semaphore mutex=1;//互斥访问缓冲区
Producer():
	P(empty);
		P(mutex):
			填充buffer;
		V(mutex);
		V(full);
 Consumer():
	P(full):	
		P(mutex):
		消费buffer;
		V(mutex);
	V(empty);
	

  1. 管程解决
monitor PC{//管程本身实现了互斥,无限互斥信号量
    int in=0,out=0,count=0;
    item buffer[n];
    condition empty,full;//需要资源信号量,条件变量
    
    put(item){
        if(count>=n)
            full.wait();
        buffer[in]=item;
        in=(in+1)%n;
        count++;
        if(empty.queue)
            empty.signal();
    }
    
    get(){
        if(count<=0){
            empty.wait();
        }
        item=buffer[out];
        out=(out+1)%n;
        count--;
        if(full.queue){
            full.signal();
        }
        return item;
    }
    
}
  1. 与进程的执行顺序有关的问题

资源信号量P、V操作分布在不同进程
互斥信号量P、V操作出现在同一进程

semaphore mutex1=1,mutex2=1;
semaphore empty1=1,empty2=1;//分别表示缓冲区1及缓冲区2是否为空,初值为1。
semaphore full1=0,full2=0;//分别表示缓冲区1及缓冲区2是否有记录可供处理,初值为0

PA(){
    while(1){
        从磁盘读一个记录;
        P(empty1):
        	P(mutex1):
        		将记录存入缓冲区1;
        	V(mutex1);
        	V(full1);
    }
    
}
PB(){
    while(1){
        P(full1):
        		P(mutex1):
        			P(empty2):
        				P(mutex2):
        					从缓冲区1中取出记录放去缓冲区2;
        		V(mutex1);
        		V(empty1);
        		V(mutex2);
        		V(full2);
    }
}
PC(){
    while(1){
        P(full2):
        	P(mutex2):
        		从缓冲区2读打印;
        	V(mutex2);
        	V(empty2);
        	
    }
}
Main(){
    parbegin()
        PA();
    	PB();
    	PC();
    parend;
}
  1. 读者/写者问题:Readers-Writers Problem
    三个角色
    一个共享的数据区;
    Reader: 只读取这个数据区的进程;
    Write: 只往数据区中写数据的进程;
    三个条件
    多个Reader可同时读数据区;
    一次只有一个Writer可以往数据区写;
    数据区不允许同时读写。
int readcount=0;
semaphore mrc=1,r=1,w=1;
Reader{
 
    
    读书;
    P(mrc):
    	readcount--;
    	if(readcount==0):
    		V(w);
    V(mrc);
      
}
Writer{
    P(r):
    	P(w):;
    	V(w);
    V(r);              
}
  1. 哲学家就餐问题
  • 最多允许4个哲学家同时进食
//为资源(餐叉)分配一个偏序关系,所有资源都按此顺序获取,按照相反顺序释放
//给哲学课编号,奇数号的哲学家必须首先拿左边的筷子,偶数号的哲学家则反之
semaphore fork[5]={1,1,1,1,1};
int i;
void philosopher(int i){
	while(i){
        think();
        if(i%2==0){
            P(fork(i));
            P(fork[(i+1)%5]);
        }else{
            P(fork[(i+1)%5]);
            P(fork[i]);
        }
        eat();
        V(fork[(i+1)%5]);
        V(fork[i]);
    }
}
  1. 哲学家升级版本:

    餐叉编号为1至5,每个哲学家总是先拿起左右两边编号较低的餐叉,再拿编号较高的。用完餐叉后,他总是先放下编号较高的餐叉,再放下编号较低的。

#define N 5
#define LEFT (i-1+N)%N
#define RIGHT (i+1)%N
#define THINKING 0
#define HUNGRY 1
#define EATING 2
int state[N]={0,0,0,0,0};
semaphore mutex=1;
semaphore s[N]={0,0,0,0,0};
take_forks(int i):{
    P(mutex):
        state[i]=HUNGRY;
        test[i];
    V(mutex);
    P(s[i]);
}
put_forks(i){
    P(mutex):
    	state[i]=THINKING;
    	test(LEFT);
    	test(RIGHT);
    	test(RIGHT);
    V(mutex);
    	
}
test(i){
    //如果只有一边的刀叉就绪,直接退出 if,只有两边就绪才会进入 if。从效果上看,就是 test(i-1) 可能什么效果都没有,test(i+1) 会设置。 
    if(state[i]==HUNGRY&&state[LEFT]!=EATING&&state[RIGHT]!=EATING){
        state[i]=EATING;
        V(s[i]);
    }

}
//管程解法
#define N 5
#define THINKING 0
#define HUNGRY 1
#define EATING 2
monitor philosopherMal{
    int state[N]={0,0,0,0,0};
    condition self[N]={0,0,0,0,0};
	void test(int i){
    	if(state[i]==HUNGRY)&&(state[(i+4)%5]!=EATING)&&(state[i+1]%5!=EATING){
            state[i]=EATING;
            self[i].signal;
        }
    void take_forks(int i){
        state[i]=HUNGRY;
        test(i);
        if(state[i]!=EATING){
            self[i].wait();
        }
    }
     void put_forks(int i){
         state[i]=HUNGRY;
         test((i+4)%N);
         test((i+1)%N);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值