操作系统:PV操作


信号量机制是一种功能较强的机制,可用来解决互斥和同步的问题,它只能被两个标准的原语访问。

P – 申请/占有空间 wait(s)

V – 释放资源 signal(s)

整型信号量

wait(s){
  while(s<=0);
  s = s - 1; //P操作 占用一个资源
}

signal(s){
  s = s + 1;  // V操作 释放一个资源
}

利用信号量实现同步

同步:要让并发的进程按要求有序的推进

//前V(s)后P(s)
//如下,执行y时需要x的计算结果,因此需要先执行x再执行y
semaphore s = 0;

P1(){
  ...
    
  x;
  //释放s=1
  V(s);
}

P2(){
  ...
  //经过v(s)后,可申请到s;否则申请不到s
  P(s);  
  y;  
}

利用信号量实现互斥

互斥:某些临界资源,只可以互斥访问

semaphore s = 1;

P1(){
  ...
  P(s);   //s=0
  访问临界资源;   //临界区
  V(s);
}

P2(){
  ...
  P(s);  
  访问临界资源;
  V(s);
}

在pv操作的同步和互斥的关系中,若某一种行为需要某种资源,“P一下”这种资源;而当需要释放某种资源时,我们就“V一下”这种资源

PV总是成对出现;当出现互斥关系时,将临界区的代码夹在中间,一气呵成

生产者消费者问题

问题描述: 一组生产者进程和一组消费者进程共享大小为n的缓冲区,只有缓冲区没满时,生产者才能把信息放入缓冲区;只有缓冲区不为空时,消费者才能从中取出信息。同时只允许一个生产者或消费者同时在缓冲区操作。

分析: 互斥访问;只有生产者生产后,消费者才能消费。

semaphore mutex = 1;   //临界互斥信号量
semaphore empty = n;   //空闲缓冲区
semaphore full = 0;    //初始缓冲区为空

//生产者进程
producer(){
  while(1){
    produce data;       //生产
    P(empty);
    P(mutex);
    add data to buffer;  //放入缓冲区
    V(mutex);
    V(full);
  }
}

//消费者进程
consumer(){
  while(1){
    P(full);          
    P(mutex);
    remove data to buffer;
    V(mutex);
    V(empty);
  }
}

读者-写者问题

约束条件:

  1. 允许多个读者在同时对文件执行读操作(读进程可同时访问
  2. 只允许一个写者往文件里写信息
  3. 任一写者在完成写操作前,不允许其他读者或写者工作(写进程和读写进程均互斥
  4. 写者执行操作前将已有的读者和写者推出
int count = 0;     //计数器
semaphore rw = 1;

writer(){
  while(1){
    P(rw);
    writing;
    V(rw);
  }
}

reader(){
  while(1){
  /****************/  
    P(mutex);
    if(count == 0){ //判断是不是第一个读者
      P(rw);
      count++;
    V(mutex);
  /****************/    
      reading;
  /****************/  
      P(mutex);
      count--;
      if(count == 0)  //判断是不是最后一个读者
        V(rw);
      V(mutex);
  /****************/  
      
    }
  }
}

读进程和读进程可同时访问,第二个以及后续读者进入时不需要再申请rw,只需要 count++ 进行计数;

当读完后读者退出执行count- -,当count=0时,最后一个读者读完再释放rw

用count判断是否是第一个/最后一个读者(读进程

哲学家进餐问题

问题描述: 有五个哲学家共用一张圆桌,在圆桌上有五个碗和五支筷子。平时哲学家进行思考,饥饿时便试图取其左、右最靠近他的筷子,只有在他拿到两支筷子时才能进餐,该哲学家进餐完毕后,放下左右两只筷子又继续思考。

约束条件

  1. 只有拿到两只筷子时,哲学家才能吃饭;
  2. 如果筷子已被别人拿走,则必须等别人吃完之后才能拿到筷子;
  3. 任一哲学家在自己未拿到两只筷子吃完饭前,不会放下手中已经拿到的筷子(易产生死锁)。
semaphore chopstick[5] = {1,1,1,1,1}; 
semaphore mutex = 1;

Pi(){
  while(1){
    P(mutex);    //对拿筷子的过程用互斥锁
    P(chopstick[i]);    //取左边筷子
    P(chopstick[(i+1)%5]); //取右边筷子
    V(mutex);
    eat;
    V(chopstick[i]);    //放下左筷子
    V(chopstick[(i+1)%5]);
    think;
  }
}

在哲学家拿起左边筷子的过程中,右边的筷子不能被其他的哲学家拿走,因此需要使用互斥锁,防止死锁

吸烟者问题

问题描述: 有三个抽烟者进程和一个供应者进程。每个抽烟者不停地卷烟并抽掉它,但是要卷起并抽调一支烟,抽烟者需要有三种材料:烟草、纸和胶水。三个抽烟者中,第一、二、三个分别拥有烟草、纸和胶水。供应者进程无限提供三种材料,供应者每次将两种材料放桌子上,拥有剩下那种材料的抽烟者卷一根烟并抽掉它,并给供应者进程一个信号告诉完成了,供应者就放另外两种材料在桌子上,这个过程一直重复,让三个抽烟者轮流地抽烟。

分析: 供应者和三个抽烟者是同步关系;三个抽烟者对抽烟是互斥关系

int num = 0;  //存储随机数,实现轮流抽烟
semaphore offer1 = 0;   //1 2 3分别表示需要三种原材料
semaphore offer2 = 0;
semaphore offer3 = 0;
semaphore finish = 0;   //表示抽烟是否完成

//供应者进程
process P1(){
  while(1){
    num++;
    num = num % 3; //轮流
    if(num == 0)
      V(offer1);
    else if(num == 1)
      V(offer2);
    else V(offer3);
    
    P(finish);  //申请finish,告诉吸烟者可以拿材料了
  }
}

process P2(){
  while(1){
    P(offer3);
    抽烟;
    V(finish);   //释放finish,告诉供应者进程完成了
  }
}
process P3(){
    P(offer2);
    抽烟;
    V(finish);
}
process P4(){
    P(offer1);
    抽烟;
    V(finish);
}
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值