操作系统PV操作之——生产者消费者模型

本文详细介绍了操作系统中的PV操作,包括信号量的定义、应用以及在解决生产者消费者模型中的应用。通过实例解析了单生产单消费及多生产者多消费者的情况,并针对多生产者多消费者模型提出了防止线程安全问题的解决方案。
摘要由CSDN通过智能技术生成

操作系统PV操作之——生产者消费者模型

个人博客主页
参考资料:
Java实现PV操作 | 生产者与消费者

浙大公开课

在操作系统的多进程、多线程操作中经常会有因为同步、互斥等等问题引发出的一系列问题,我们的前辈为了解决这些问题,发明出了“信号量(Semaphore)”这么一个令人称奇的变量,就目前来看,很巧妙的解决了这些问题。

  • 信号量是个整形变量
  • 信号量S只允许两个标准操作wait()和signal(),或者他的发明者称呼的P操作和V操作
  • wait()和signal()是原子操作,不可分割的原语

对PV操作的定义

对PV操作的定义不是单一的,这里举个比较简单的例子

/*P操作*/
wait(S){
    value--;
    if(value < 0){
	/*value的大小表示了允许同时进入临界区进行操作的
	  进程数量*/
        /*add this process to waiting queue*/
        block();
    }
}

/*V操作*/
signal(S){
    value++;
    if(value <= 0){
	/*因为P操作是当value<0时休眠一个线程,说明如果有休眠
	  的线程,则value一定小于0,所以此时当value+1后,如果
	  还有休眠的线程,value必定小于或等于0 */
        /*remove a process P from the waiting queue*/
        wakeup(P);
    }
}

信号量的应用

  1. 临界区(互斥)问题,信号量初值需要置为1,表示只能有一个进程进入临界区,从而保护临界区内的数据同时只能被一个进程访问,避免出现多个进程同时操作同一个数据。

    Semaphore S;        //初始值为1
    do{
        wait(S);
            Critical Section;		//临界区
        signal(S);
            remainder section	//剩余部分
    }while(1);
    
  2. 两个进程的同步问题。假如有两个进程 Pi和Pj,Pi有个A语句(输入x的值),Pj有个B语句(输出x+1的值),希望在B语句执行之前A语句已经执行完成。

    //同步,定义信号量flag初值为0,等待方用wait操作,被等待方用signal操作,还要紧贴着放
    Pi进程							Pj进程
        ...							...
       	A						 wait(flag)
     signal(flag)						B
        ...							...
    

生产者消费者模型

先定义出PV操作的类

/**
 * 封装的PV操作类,为了简单起见,没有用一个等待队列,而是直接用
 * Java的Object类方法中的wait方法来模拟
 * @author Vfdxvffd
 * @count 信号量
 * 这里调用wait方法和signal方法的是同一个对象this,所以V操作唤
 * 醒的只能是同一个对象P操作加入等待队列的进程
 */
class syn{
   		
	int count = 0;
	syn(){
   }
	syn(int a){
   count = a;}	//给信号量赋初值
	
	public synchronized void Wait() {
   
		count--;
		if(count < 0) {
   		//block
             /*add this process to waiting queue*/
			try {
   
				wait();
			} catch (InterruptedException e) {
   
				e.printStackTrace();
			}
		}
	}
	
	public synchronized void Signal() {
   
		count++;
		if(count <= 0) {
   	//wakeup
            /*remove a process P from the waiting queue*/
			notify();
		}
	}
}

单生产单消费(PV操作解决同步问题)

  1. 先引入全局的信号量,将其封装在一个类中

    class Global{
         
    	static syn empty = new syn(2);	//成员变量count表示剩余空闲缓冲区的数量, >0则生产者进程可以执行
    	static syn full = new syn(0);	//成员变量count表示当前待消费物品的数量, >0则消费者进程可以执行
    	static int[] buffer = new int[2];	//缓冲区数组,大小代表缓冲区的数量,即放面包的盘子
    }
    
  2. 生产者类

    /**
     * 单个生产者类
     * @author Vfdxvffd
     * @count 生产的物品数量标号
     */
    class Producer implements Runnable{
         
    	int count = 0;		//数量
    	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值