PV操作--demo test

前言
操作系统的pv操作的认识,每次都有不一样的感受,近期自己再一次接触到PV操作,生产者消费者的问题,从代码的角度体会了一下,有不一样的认识和体会。
认识
信号量(Saphore)由一个值和一个指针组成,指针指向等待该信号量的进程。信号量的值表示相应资源的使用情况。信号量S>=0时,S表示可用资源的数量。执行一次P操作意味着请求分配一个资源,因此S的值减1;当S<0时,表示已经没有可用资源,S的绝对值表示当前等待该资源的进程数。请求者必须等待其他进程释放该类资源,才能继续运行。而执行一个V操作意味着释放一个资源,因此S的值加1;若S<0,表示有某些进程正在等待该资源,因此要唤醒一个等待状态的进程,使之运行下去。
Alt
这里写图片描述
对于PV操作的一些疑问:
S大于0的时候不唤醒资源,小于0的时候为什么要唤醒资源?
S大于0表示,有临界资源可以使用,也就是这个时候没有进程阻塞在资源上,所以不需要被唤醒。S小于0的时候,我们要说一下V操作的原语,本质在于:一个进程使用完临界资源后,释放临界资源,使S加1,以通知其它的进程,这个时候如果S<0,表明有进程阻塞在该类资源上,因此要从阻塞队列里唤醒一个进程来“转手”该类资源,所以这个的前提是V操作哦。
S的绝对值表示等待的进程数,同时又表示临界资源,如何区分一下呢?
当信号量S小于0时,其绝对值表示系统中因请求该类资源而被阻塞的进程数目.S大于0时表示可用的临界资源数。注意在不同情况下所表达的含义不一样。当等于0时,表示刚好用完。
demo
一下是动手实现的一个demo,感觉挺有意思的:

//生产者消费者问题
//客户端
public class ProducerConsumer{
  public static void main(String[] args){
      SyncStack ss =new SyncStack();
      Producer p =new Producer(ss);
      Customer c =new Customer(ss);
      new Thread(p).start();
      new Thread(c).start();

  }
}

//生产的产品
class Product{
  int id;
  //构造函数
  Product(int _id){
      this.id=_id;
  }

  public String toString(){
      return "产品:"+id;
  }
}

//容器
class SyncStack{
  int index=0;
  Product[] Arrpro =new Product[10];  //容器最多可以放10个产品

  //容器中放产品的方法
  public synchronized void push(Product pro){
      //如果满了
      if(index ==Arrpro.length){
          try{
              this.wait();
          }catch(InterruptedException e){
              e.printStackTrace();
          }
      }
      this.notify(); //唤醒正在等待的线程

      Arrpro[index]=pro;
      index++;
  }
  //容器中取产品
  public  synchronized Product pull(){
      if(index ==0){
          try{
              this.wait();
          }catch(InterruptedException e){
              e.printStackTrace();
          }

      }
      this.notify(); //唤醒正在等待的线程
      index--;
      return Arrpro[index];

  }
}

//生产者--申请一个线程
class Producer implements Runnable{
  SyncStack ss =new SyncStack();
  Producer(SyncStack _ss){
      this.ss=_ss;
  }
  public void run(){
      //生产者能够造20个产品
      for(int i=0;i<20;i++){
          Product pro=new Product(i);
          ss.push(pro);
          System.out.println("生产了"+pro);
          try{
              Thread.sleep(1000);
          }catch (InterruptedException e){
              e.printStackTrace();
          }
      }
  }
}

//消费者
class Customer  implements Runnable{
  SyncStack ss =new SyncStack();
  Customer(SyncStack _ss){
      this.ss=_ss;
  }

  public void run(){
      for(int i=0;i< 20;i++){
          Product pro =ss.pull();
          System.out.println("消费了"+pro);

          try{
              Thread.sleep(2000);
          }catch (InterruptedException e){
              e.printStackTrace();
          }
      }       
  }
}

结语
学习是在不断的认识,不断重复的基础上的,每次学习都get到一个点,会觉得很有意思。
转自:Viola_tt

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值