生产者消费者实验报告

时间:2024.5.13

杭州电子科技大学

实验课程名称      《计算机操作系统》    

开 课 学 院         软件工程学院        

指导老师姓名        任一支              

学 生 姓 名   王体方 王雁飞 谷莉莎 陆文英

学生专业班级  软件工程10108412 10108413

2012  —  2013  学年  第一学期

生产者消费者实验

实验内容:

以生产者消费者模型为依据,提供一个多线程生产者-消费者实例,用VC或java实现,并具备以下功能:

(1)       可改变缓冲区数目;

(2)       可增加或减少线程数目;

(3)       改变延迟时间;

(4)       可增加或减少生产者、消费者进程数目;

(5)       可改变消费者进程请求序列;

一、流程图:

 


二、源代码:

package pro_con;

publicclassMain

{

   publicstaticvoid main(String[] args)

   {

         new Main().start();

   }

  

   public  void start()

   {

      Buffers buffers=new Buffers(5);

      String [] idList4={"5","6"};

      String [] idList7={"1","3","5"};

      new Pro_Thread("生产者 1",buffers,5,"1").start();

      new Pro_Thread("生产者 2",buffers,4,"2").start();

      new Pro_Thread("生产者 3",buffers,2,"3").start();

      new Pro_Thread("生产者 5",buffers,7,"5").start();

      new Pro_Thread("生产者 6",buffers,1,"6").start();

      new Con_Thread("消费者 4",buffers,6,idList4).start();

      new Con_Thread("消费者 7",buffers,3,idList7).start();

   }

}

Buffers.java:

package pro_con;

//缓冲区

publicclassBuffers

{

    privateintproductNum;//缓冲单元数目

    publicstaticProductproducts[];//缓冲区队列

    privateintcount=0;   //记录使用的缓冲区单元

   public Buffers(int productNum)

   {

      super();

      this.productNum= productNum;

      this.products=newProduct[productNum];

      this.initBuffersPool();

   }

   //初始化该缓冲区

   publicvoid initBuffersPool()

   {

      for (int i =0; i <products.length; i++)

      {

        products[i] =new Product();

        products[i].setProductId("-1");

      }

   }

   //取出产品

   public  synchronizedProduct get(String id)

   {

      Product product =null;

      while(count==0)

      {

        try

        {

           super.wait();

        } catch (InterruptedException e)

        {

           e.printStackTrace();

        }

      }

      this.notifyAll();  

      int x =-1;

      int i =0;

      for (i =0; i <products.length; i++)

      {

           if(products[i].getProductId().equals(id))

           {

              x = i;

              product =products[i];

              products[i].setProductId("-1");

              break;

           }

          

      }

      while(i ==products.length)

      {

        try

        {

           super.wait();

           for (i =0; i <products.length; i++)

           {

              if(products[i].getProductId() == id)

              {

                    x = i;

                    product =products[i];

                    products[i].setProductId("-1");

                    break;

                 }

                

              }

           } catch (InterruptedException e)

           {

              e.printStackTrace();

           }

        }

        notifyAll();        System.out.println(Thread.currentThread().getName() +" 开始消费 \t"   + id +"产品");

        count--;

   System.out.println(Thread.currentThread().getName() +" 成功消费\t"+ id +"产品\n");

   System.out.println("缓冲区 ["+ x +"]\t"+products[x]+"\n");

      return product;

   }

    //添加产品

   public  synchronizedboolean put(String productId)

   {

      boolean bool =false;

     

      //如果满了,就等待消费者消费

      while(count==products.length)

      {

        try{

           super.wait();

        }catch(Exception e){

           e.printStackTrace();

        }

      }

      this.notifyAll();

     

      int i = findPutLocation();

      System.out.println(Thread.currentThread().getName() +" 开始在\t缓冲区"

           + i +"\t生产");

      bool =true;

      products[i].setProductId(productId);

      count++;

      System.out.println(Thread.currentThread().getName() +" 完成生产\n");

      System.out.println("缓冲区 ["+ i +"]\t"+products[i]+"\n");

     

      return bool;

   }

    //找一个合适的位置

   publicsynchronizedint findPutLocation()

   {

      int k =0;

      for (int i =0; i <products.length; i++)

      {

        if(products[i].getProductId().equals("-1"))

        {

           k = i;

           break;

        }

      }

      return k;

   }

}

Product.java:

package pro_con;

//产品

publicclassProduct

{  

    privateString  productId;

  

   publicString getProductId()

   {

      returnproductId;

   }

   publicvoid setProductId(String productId)

   {

      this.productId= productId;

   }

   publicString toString()

   {

      returnproductId;

   }

   

}

消费者线程:

Con_Thread.java:

package pro_con;

publicclassCon_ThreadextendsThread

{

   privatestaticfinalint baseTime =1000;

   privateStringidList[];//消费者消费产品

   privateintn;// 延迟时间

   privateBuffersbuffers;

    privateinti=0;

  public Con_Thread(String name,Buffers buffers,int n,String idList[])

   {

      super(name);

      this.idList= idList;

      this.n= n;

      this.buffers= buffers;

   }

   @Override

   publicvoid run()

   {

      while (i<idList.length)

      {

        try

        {

           Thread.sleep(n* baseTime);

           System.out.println(Thread.currentThread().getName() +" 请求消费\t"

                 +idList[i] +"产品");

           buffers.get(idList[i]);

           ++i;

        } catch (InterruptedException e)

        {

           e.printStackTrace();

        }

      }

   }

}

生产者线程:

Pro_Thread.java:

package pro_con;

publicclassPro_ThreadextendsThread

{

   privatestaticfinalint baseTime =1000;

   privateBuffersbuffers;

    privateintn;

    privateStringid;

   public Pro_Thread(String name ,Buffers buffers,int n,String id)

   {

      super(name);

      this.n= n;

      this.buffers=buffers;

      this.id= id;

   }

   @Override

   publicvoid run()

   {

        try

        {

           Thread.sleep(n*baseTime);

           System.out.println(Thread.currentThread().getName() +" 发出请求生产信号");

           buffers.put(id);

        } catch (InterruptedException e)

        {

           e.printStackTrace();

        }

   }

}

三、测试用例:

输出结果为:


第二篇:操作系统实验报告 经典的生产者—消费者问题


实验二  经典的生产者—消费者问题

一、目的

实现对经典的生产者—消费者问题的模拟,以便更好的理解经典进程同步问题。

二、实验内容及要求

编制生产者—消费者算法,模拟一个生产者、一个消费者,共享一个缓冲池的情形。

1、实现对经典的生产者—消费者问题的模拟,以便更好的理解此经典进程同步问题。生产者-消费者问题是典型的PV操作问题,假设系统中有一个比较大的缓冲池,生产者的任务是只要缓冲池未满就可以将生产出的产品放入其中,而消费者的任务是只要缓冲池未空就可以从缓冲池中拿走产品。缓冲池被占用时,任何进程都不能访问。

2、每一个生产者都要把自己生产的产品放入缓冲池,每个消费者从缓冲池中取走产品消费。在这种情况下,生产者消费者进程同步,因为只有通过互通消息才知道是否能存入产品或者取走产品。他们之间也存在互斥,即生产者消费者必须互斥访问缓冲池,即不能有两个以上的进程同时进行。

三、生产者和消费者原理分析

在同一个进程地址空间内执行两个线程。生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放一个空缓冲区。当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻挡,直到新的物品被生产出来。

四、生产者与消费者功能描述:

生产者功能描述:在同一个进程地址空间内执行两个线程。生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。

消费者功能描述:消费者线程从缓冲区获得物品,然后释放缓冲区,当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。

五、实验环境

操作系统环境:Windows系统。

编程语言:C#。

六、生产者与消费者的思路和设计

1、程序流程图

(1) 生产者

 


                                                                                 


(2) 消费者

 

2、主要程序代码

//初始化变量

       private void Form1_Load(object sender, EventArgs e)

        {

            mutex = 1;   //互斥信号量

            full = 0;   //缓冲池中满缓冲区的数量

            empty = 5;//缓冲池中空缓冲区的数量

            count1 = 0;//生产的产品数目

            i = 0;

            lb_mutex.Text = "1";

            lb_full.Text = "0";

            lb_empty.Text = "5";

         }

//消费者从缓冲区中消费一个产品

 private void consumer_Click(object sender, EventArgs e)

 {

      if (full > 0)

     {                          //消费者已进入互斥临界区

         if (mutex == 1)           //申请进入临界区

         {

             mutex = 0;           //消费者已进入互斥临界区

             lb_mutex.Text = "0";

             timer_consumer.Enabled = true;//启动消费者消费缓冲区产品

}

         else

         {

             MessageBox.Show("缓冲区被占用,请等待。。。", "信息提"MessageBoxButtons.OK);

         }

}

       else

      {

         MessageBox.Show("缓冲区为空,不能消费!", "信息提示", MessageBoxButtons.OK);

       }

 }

//生产者向缓冲区中存入一个产品

 private void producer_Click(object sender, EventArgs e)

 {

    count1 = count1 + 1;             //生产一个产品

    if (empty > 0)

    {                             //有缓冲区可放产品

      if (mutex == 1)

      {                           //申请进入临界区

        mutex = 0;                 //生产者已进入临界区

        lb_mutex.Text = "0";

timer1.Start();              //启动生产者将产品放入缓冲区

        }

else

       {                          //不能进入临界区

          count1 = count1 - 1;

          MessageBox.Show("缓冲区被占用,请等待。。。", "信息提示", MessageBoxButtons.OK);

}

      }

    else

    {

       MessageBox.Show("缓冲区已满!", "信息提示", MessageBoxButtons.OK);    //无缓冲区可放产品

       count1 = count1 - 1;

     }

  }

//生产者

 private void timer1_Tick_1(object sender, EventArgs e)

 {

     if (bool1)

     {

         switch (count1)

         {

             case 1: pictureBox1.Visible = true; break;

             case 2: pictureBox2.Visible = true; break;

             case 3: pictureBox3.Visible = true; break;

             case 4: pictureBox4.Visible = true; break;

             case 5: pictureBox5.Visible = true; break;

         }

         lb_show.Text = "生产者进程占用缓冲区,请等待。。。。";

         bool1 = false;

     }

     else

      {

         switch (count1)

         {

             case 1: pictureBox1.Visible = false; break;

             case 2: pictureBox2.Visible = false; break;

             case 3: pictureBox3.Visible = false; break;

             case 4: pictureBox4.Visible = false; break;

             case 5: pictureBox5.Visible = false; break;

         }

         lb_show.Text = "生产者进程占用缓冲区,请等待。。。。";

         bool1 = true;

     }

     i = i + 1;

     if (i == 5)

     {                      //循环缓冲区,首尾相接

         i = 0;

         timer1.Enabled = false;

         mutex = 1;

         lb_mutex.Text = "1";

         switch (count1)

         {

             case 1: pictureBox1.Visible = true; break;

             case 2: pictureBox2.Visible = true; break;

             case 3: pictureBox3.Visible = true; break;

             case 4: pictureBox4.Visible = true; break;

             case 5: pictureBox5.Visible = true; break;

         }

         full = full + 1;

         lb_full.Text = full.ToString();

         empty = empty - 1;

         lb_empty.Text = empty.ToString();

         lb_show.Text = "生产结束!";

     }

 }

//消费者

 private void timer_consumer_Tick(object sender, EventArgs e)

 {

  if(bool1){

            switch(count1){

                 case 1: pictureBox1.Visible = true; break;

                 case 2: pictureBox2.Visible = true; break;

                 case 3: pictureBox3.Visible = true; break;

                 case 4: pictureBox4.Visible = true; break;

                 case 5: pictureBox5.Visible = true; break;

                 }

          lb_show.Text = "消费者进程占用缓冲区,请等待。。。。";

             bool1 =false;

     }

     else{

           switch(count1){

             case 1: pictureBox1.Visible = false; break;

             case 2: pictureBox2.Visible = false; break;

             case 3: pictureBox3.Visible = false; break;

             case 4: pictureBox4.Visible = false; break;

             case 5: pictureBox5.Visible = false; break;

              }

       lb_show.Text= "消费者进程占用缓冲区,请等待。。。。";

       bool1= true;

     }

i = i + 1;

       if(i==5){

     i = 0;

     timer_consumer.Enabled = false;

        mutex = 1;

lb_mutex.Text= "1";

       switch(count1){

            case 1: pictureBox1.Visible = false; break;

            case 2:  pictureBox2.Visible = false; break;

            case 3: pictureBox3.Visible = false; break;

            case 4: pictureBox4.Visible = false; break;

            case 5: pictureBox5.Visible = false; break;

           }

count1 = count1 - 1;

full = full - 1;

lb_full.Text = full.ToString();

empty = empty+1;

        lb_empty.Text=empty.ToString();

        lb_show.Text="消费结束!";

   }

3、运行界面和运行结果

一般情况下,点一次生产者按纽,mutex由1变为0,缓冲区呈现闪烁状态(表示正在存储),此时不可以再进行缓冲区操作,否则将显示“生产者进程正在占用缓冲区,请等待”。闪烁约1.5秒后,mutex由0变为1,闪烁停止,表示存储过程结束;点一次消费者按纽,mutex由1变为0,缓冲区呈现闪烁状态(表示正在消费),此时不可以再进行缓冲区操作,否则将显示“消费者进程正在占用缓冲区,请等待”。闪烁约1.5秒后,mutex由0变为1,闪烁停止,表示消费过程结束。

缓冲池满后,若再点生产者按纽,会给出信息提示:“缓冲区已满!”。

缓冲池空后,若再点消费者按纽,也会给出信息提示:“缓冲区为空,不能消费!”。

在存储状态或消费状态(闪烁状态),无论是点生产者按纽还是消费者按纽都会给出“缓冲区被占用,请等待。。”信息提示。

七、心得体会

本次实验是关于生产者与消费者之间互斥和同步的问题。问题的是指是P、V操作,实验设一个共享缓冲区,生产者和消费者互斥的使用,当一个线程使用缓冲区的时候,另一个让其等待直到前一个线程释放缓冲区为止。

生产者与消费者是一个与现实有关的经验问题,通过此原理举一反三可以解决其他类似的问题。

通过本实验设计,我们对操作系统的P、V进一步的认识,深入的了解P、V操作的实质和其重要性。课本的理论知识进一步阐述了现实中的实际问题。

实验中,我们小组分工合作,共同学习,虽然在实验中遇到了一些问题,但在老师和同学的细心指导和热心帮助下解决了。同时,了解到团队精神的重要性,也为以后的学习和工作打下了坚实的基础,同时积累了宝贵的经验。

更多相关推荐:
生产者与消费者实验报告

生产者和消费者实验报告实验目的1加深对进程概念的理解明确进程和程序的区别2进一步认识并发执行的实质3验证用信号量机制实现进程互斥的方法4验证用信号量机制实现进程同步的方法实验要求用c语言编程搭建生产者和消费者经...

实验报告五 生产者和消费者问题

实验报告五生产者和消费者问题姓名丛菲学号20xx0830205班级信息安全二班一实习内容1模拟操作系统中进程同步和互斥2实现生产者和消费者问题的算法实现二实习目的1熟悉临界资源信号量及PV操作的定义与物理意义2...

《操作系统》实验报告 生产者——消费者

数学与信息技术学院南京晓庄学院操作系统实验报告指导老师专业班级学号姓名完成日期数学与信息技术学院1数学与信息技术学院一实验概述1实验目的深入了解掌握进程的同步互斥机制认识理解其调度过程并用于解决实际生产者消费者...

操作系统生产者与消费者问题实验报告

操作系统实验报告生产者和消费者的问题一实验目的1掌握基本的同步与互斥的算法理解基本的生产者与消费者的模型2学习使用Windows20xxXP中基本的同步对象掌握相关的API的使用方法3了解Windows20xx...

生产者消费者问题实验报告

操作系统课程设计实验报告实验名称生产者消费者问题姓名学号一实验目的以生产者和消费者问题为例学习Linux和Windows下进程通信同步机制的具体实现方法主要是信号量和共享内存熟悉相关系统API的用法二实验内容使...

生产者消费者实验报告

实验二生产者与消费者进程实验报告实验目的利用Windows提供的API函数编写程序解决生产者与消费者问题实现进程的互斥与同步实验内容与步骤1进程的互斥与同步编写一段程序模拟生产者和消费者线程实现进程的互斥与同步...

生产者与消费者实验报告

一实验目的利用Windows提供的API函数编写程序解决生产者与消费者问题实现进程的互斥与同步二实验内容本实验要求设计在同一个进程地址空间内执行的两个线程生产者线程生产物品然后将物品放置在一个空缓冲区中供消费者...

操作系统实验报告生产者消费者问题

操作系统实验报告20xx年1月8日指导教师对实验报告的评语成绩指导教师签字年月日一设计目标完成N个生产者和M个消费者线程之间的并发控制NM不低于30数据发送和接收缓冲区尺寸不小于20个每个产品占据一个其中生产者...

操作系统实验报告 生产者-消费者问题算法的实现

肇庆学院计算机学院实验报告专业网络工程班级学年20xx20xx实验名称实验四实验内容实验时间20xx年5月9日1问题描述一组生产者向一组消费者提供消息它们共享一个有界缓冲池生产者向其中投放消息消费者从中取得消息...

生产者-消费者操作系统实验报告

一目的和要求在采用多道程序设计的系统中往往有若干个进程并发执行进程之间存在相互制约关系本实验模拟在单处理器情况下的进程并发执行过程中如何利用信号量机制实现并发进程的同步和互斥帮助学生加深了解信号量机制进程的同步...

并发控制-生产者-消费者问题实验报告

课程设计报告课程名称基于Windows的课程设计年级专业班计算机093班学生姓名学号指导老师题目并发控制生产者消费者问题完成时间20xx1120一设计要求lt1gt完成N个生产者和M个消费者之间的并发控制NM不...

操作系统实验报告生产者消费者问题

操作系统实验报告20xx年1月2日指导教师对实验报告的评语成绩指导教师签字年月日一设计目标完成N个生产者和M个消费者线程之间的并发控制NM不低于30数据发送和接收缓冲区尺寸不小于20个每个产品占据一个其中生产者...

生产者消费者实验报告(25篇)