实验报告--生产者

时间:2024.5.4

实验报告

课程名称:    java程序设计   

题    目:     生产者消费者    

院 (系):    信息与控制工程  

专业班级:     计算机1202      

姓    名:       张金涛         

学    号:      120620226        

指导教师:         张翔           

                               20##年 12 月 17 月

一、实验目的

实现生产者-消费者问题,深刻理解进程同步问题。 

二、实验环境

装有jdk及eclipse的计算机一台

三、实验内容

Java程序实现生产者消费者问题

四、代码及注释

 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.加深对进程概念的理解,明确进程和程序的区别。

2.进一步认识并发执行的实质。

3.验证用信号量机制实现进程互斥的方法。

4.验证用信号量机制实现进程同步的方法。

【实验要求】

用c语言编程搭建“生产者和消费者”经典进程通信问题的环境。要求程序运行时,按任意键停止,显示当前系统的各个参数的值。提交实验报告,以及相关程序列表。打包成附件上传。

【实验环境】

Visual C++6.0

【实验内容】

1.了解经典同步问题“生产者和消费者”

生产者与消费者可以通过一个环形缓冲池联系起来,环形缓冲池由几个大小相等的缓冲块组成,每个缓冲块容纳一个产品。每个生产者可不断地每次往缓冲池中送一个生产产品,而每个消费者则可不断地每次从缓冲池中取出一个产品。指针i和指针j分别指出当前的第一个空缓冲块和第一个满缓冲块。

2.分析和理解

(1)既存在合作同步问题,也存在临界区互斥问题

合作同步:当缓冲池全满时,表示供过于求,生产者必须等待,同时唤醒消费者;当缓冲池全空时,表示供不应求,消费者应等待,同时唤醒生产者。

互斥:缓冲池显然是临界资源,所在生产者与消费都要使用它,而且都要改变它的状态。

(2)基于环形缓冲区的生产者与消费者关系形式描述:

公用信号量mutex:初值为1,用于实现临界区互斥

生产者私用信号量empty:初值为n,指示空缓冲块数目

消费者私用信号量full:初值为0,指示满缓冲块数目

整型量i和j初值为0,i指示首空缓冲块序号,j指示首满缓冲块序号

(3)PV原语

var mutex,empty,full:semaphore;

i,j:integer;buffer:array[0...n-1] of item;

i:=j:=1;

Procedure producer;

begin

while true do

begin

produce a product;

P(empty);

P(mutex);

buffer(i):=product;

i:=(i+1) mod n;

V(mutex);

V(full);

end;

end;

Procedure consumer;

begin

P(full);

P(mutex);

goods:=buffer(j);

j:=(j+1) mod n;

V(mutex);

V(empty);

consume a product;

end;

end;

【实验源程序代码】

#include <windows.h>

#include <iostream>

const unsigned short SIZE_OF_BUFFER = 10; //缓冲区长度

unsigned short ProductID = 0; //产品号

unsigned short ConsumeID = 0; //将被消耗的产品号

unsigned short in = 0; //产品进缓冲区时的缓冲区下标

unsigned short out = 0; //产品出缓冲区时的缓冲区下标

int g_buffer[SIZE_OF_BUFFER]; //缓冲区是个循环队列

bool g_continue = true; //控制程序结束

HANDLE g_hMutex; //用于线程间的互斥

HANDLE g_hFullSemaphore; //当缓冲区满时迫使生产者等待

HANDLE g_hEmptySemaphore; //当缓冲区空时迫使消费者等待

DWORD WINAPI Producer(LPVOID); //生产者线程

DWORD WINAPI Consumer(LPVOID); //消费者线程

int main()

{

//创建各个互斥信号

g_hMutex = CreateMutex(NULL,FALSE,NULL);

g_hFullSemaphore = CreateSemaphore(NULL,SIZE_OF_BUFFER-1,SIZE_OF_BUFFER-1,NULL);

g_hEmptySemaphore = CreateSemaphore(NULL,0,SIZE_OF_BUFFER-1,NULL);

//调整下面的数值,可以发现,当生产者个数多于消费者个数时,

//生产速度快,生产者经常等待消费者;反之,消费者经常等待

const unsigned short PRODUCERS_COUNT = 3; //生产者的个数

const unsigned short CONSUMERS_COUNT = 1; //消费者的个数

//总的线程数

const unsigned short THREADS_COUNT = PRODUCERS_COUNT+CONSUMERS_COUNT;

HANDLE hThreads[PRODUCERS_COUNT]; //各线程的handle

DWORD producerID[CONSUMERS_COUNT]; //生产者线程的标识符

DWORD consumerID[THREADS_COUNT]; //消费者线程的标识符

//创建生产者线程

for (int i=0;i<PRODUCERS_COUNT;++i){

hThreads[i]=CreateThread(NULL,0,Producer,NULL,0,&producerID[i]);

if (hThreads[i]==NULL) return -1;

}

//创建消费者线程

for (i=0;i<CONSUMERS_COUNT;++i){

hThreads[PRODUCERS_COUNT+i]=CreateThread(NULL,0,Consumer,NULL,0,&consumerID[i]);

if (hThreads[i]==NULL) return -1;

}

while(g_continue){

if(getchar()){ //按回车后终止程序运行

g_continue = false;

}

}

return 0;

}

//生产一个产品。简单模拟了一下,仅输出新产品的ID号

void Produce()

{

std::cerr << "Producing " << ++ProductID << " ... ";

std::cerr << "Succeed" << std::endl;

}

//把新生产的产品放入缓冲区

void Append()

{

std::cerr << "Appending a product ... ";

g_buffer[in] = ProductID;

in = (in+1)%SIZE_OF_BUFFER;

std::cerr << "Succeed" << std::endl;

//输出缓冲区当前的状态

for (int i=0;i<SIZE_OF_BUFFER;++i){

std::cout << i <<": " << g_buffer[i];

if (i==in) std::cout << " <-- 生产";

if (i==out) std::cout << " <-- 消费";

std::cout << std::endl;

}

}

//从缓冲区中取出一个产品

void Take()

{

std::cerr << "Taking a product ... ";

ConsumeID = g_buffer[out];

out = (out+1)%SIZE_OF_BUFFER;

std::cerr << "Succeed" << std::endl;

//输出缓冲区当前的状态

for (int i=0;i<SIZE_OF_BUFFER;++i){

std::cout << i <<": " << g_buffer[i];

if (i==in) std::cout << " <-- 生产";

if (i==out) std::cout << " <-- 消费";

std::cout << std::endl;

}

}

//消耗一个产品

void Consume()

{

std::cerr << "Consuming " << ConsumeID << " ... ";

std::cerr << "Succeed" << std::endl;

}

//生产者

DWORD WINAPI Producer(LPVOID lpPara)

{

while(g_continue){

WaitForSingleObject(g_hFullSemaphore,INFINITE);

WaitForSingleObject(g_hMutex,INFINITE);

Produce();

Append();

Sleep(1500);

ReleaseMutex(g_hMutex);

ReleaseSemaphore(g_hEmptySemaphore,1,NULL);

}

return 0;

}

//消费者

DWORD WINAPI Consumer(LPVOID lpPara)

{

while(g_continue){

WaitForSingleObject(g_hEmptySemaphore,INFINITE);

WaitForSingleObject(g_hMutex,INFINITE);

Take();

Consume();

Sleep(1500);

ReleaseMutex(g_hMutex);

ReleaseSemaphore(g_hFullSemaphore,1,NULL);

}

return 0;

}

【实验结果】

生产者与消费者实验报告

生产者与消费者实验报告

生产者与消费者实验报告

生产者与消费者实验报告

具体程序见附件(网络查找)

【实验反思】

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

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

【实验思考题】

1.思考在“生产者和消费者”经典同步问题中,两个P操作是否可以互换位置,以及两个V操作是否可以互换位置。

在生产者—消费者问题中,如果将两个P操作,即P(full)和P(mutex)互换位置,或者P(empty)和P(mutex)互换位置,都可能引起死锁。考虑系统中缓冲区全满前时,若一生产者进程先执行了P(mutex)操作并获得成功,当再执行P(empty)操作时,它将因失败而进入阻塞状态,它期待消费者执行V(empty)来唤醒自己。在此之前,它不可能执行V(mutex)操作,从而使企图通过P(mutex)进入自己的临界区的其他生产者和所有的消费者进程全部进入阻塞状态,从而引起系统死锁。类似地,消费者进程若先执行P(mutex),后执行P(full),同样可能造成死锁。

V(full)和V(mutex)互换位置,或者V(empty)和V(mutcx)互换位置,则不会引起死锁,其影响只是使临界资源的释放略为推迟一些。

2.思考在“哲学家就餐”经典同步问题中,如何修改程序,可以保证不会发生死锁现象。

(1)至多只允许有四位哲学家同时去拿左边的筷子,最终能保证至少有一位哲学家能够进餐,并在用毕时能释放出他用过的两只筷子,从而使更多的哲学家能够进餐。

(2)仅当哲学家的左、右两只筷子均可用时,才允许他拿起筷子进餐。

(3)规定奇数号哲学家先拿他左边的筷子,然后再去拿右边的筷子,而偶数号哲学家则相反。按此规定,将是1、2号哲学家竞争1号筷子;3、4号哲学家竞争3号筷子。即五位哲学家都先竞争奇数号筷子,获得后,再去竞争偶数号筷子,最后总会有一位哲学家能获得两只筷子而进餐。

5.思考在“读者与写者”经典同步问题中,如何修改程序,变为“写者优先”的算法。

(写者优先的算法)

var rmutex,wmutex,mutex,s:semaphore=1,1,1,1;

writecount:integer:=0;

reader:begin

repeat

wait(s);

wait(rmutex);

if readcount=0 then wait(wmutex);

readcount:readcount+1;

signal(rmutex);

signal(s);

perform read operation;

wait(rmutex);

readcount:=readcount-1;

if readcount=0 then signal(wmutex);

signal(rmutex);

until false ;

end

writer:begin

repeat

wait(mutex);

if writecount=0 then wait(s);

writecount:writecount+1;

signal(mutex);

wait(wmutex);

perform write operation;

signal(wmutex);

wait(mutex);

writecount:=writecount-1;

if writecount=0 then signal(s);

signal(mutex);

until false ;

end

4. 分析以下进程运行环境中出现的同步和互斥现象,列出相应的变量和参数。理发店理有一位理发师、一把理发椅和n把供等候理发的顾客坐的椅子。如果没有顾客,理发师便在理发椅上睡觉。一个顾客到来时,它必须叫醒理发师。如果理发师正在理发时又有顾客来到,则如果有空椅子可坐,就坐下来等待,否则就离开。

  理发师是顾客争用的资源,用信号量barbers表示,初值为0;除此以外,顾客还要争用n张椅子,信号量customers表示等候理发的顾客数,初值为0;最后设置信号量mutex用于这两个活动对资源barbers、customers的互斥,初值为1。另外还需使用一个变量waiter,用于记录等候的顾客的数量。

更多相关推荐:
实验报告五 生产者和消费者问题

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

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

实验二经典的生产者消费者问题一目的实现对经典的生产者消费者问题的模拟以便更好的理解经典进程同步问题二实验内容及要求编制生产者消费者算法模拟一个生产者一个消费者共享一个缓冲池的情形1实现对经典的生产者消费者问题的...

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

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

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

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

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

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

生产者消费者实验报告

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

生产者消费者实验报告

杭州电子科技大学学生实验报告书实验课程名称计算机操作系统开课学院软件工程学院指导老师姓名任一支学生姓名王体方王雁飞谷莉莎陆文英学生专业班级软件工程101084121010841320xx20xx学年第一学期1生...

北邮操作系统消费者与生产者实验报告

操作系统实验课程报告课题消费者与生产者实验姓名学院计算机学院班级学号20xx年12月14日191实验目的1理解线程同步的思想和方法学会用线程同步解决临界区问题本次实验解决生产者消费者问题2了解windows系统...

实验二 生产者与消费者实验报告

实验二进程的互斥与同步生产者与消费者问题实验报告实验目的利用Windows提供的API函数用VISUALC60编写程序解决生产者与消费者问题实现进程的互斥与同步实验内容和步骤本实验设计在同一个进程地址空间内执行...

进程管理----生产者和消费者问题(实验报告)

进程管理----生产者和消费者问题(实验报告),内容附图。

实验二生产者和消费者

11实验目标掌握操作系统对进程管理的同步和互斥问题以经典同步问题生产者和消费者为例运用所学C语言知识编写该问题的模拟运行环境12实验环境教学机房C语言程序平台13实验内容及步骤1了解经典同步问题生产者和消费者生...

生产者消费者实验

生产者消费者实验实验内容以生产者消费者模型为依据提供一个多线程生产者消费者实例用VC或java实现并具备以下功能1可改变缓冲区数目2可增加或减少线程数目3改变延迟时间4可增加或减少生产者消费者进程数目5可改变消...

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