视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
生产者和消费者问题实验报告
2025-10-02 18:51:12 责编:小OO
文档
实 验 报 告

课程名称:      操作系统      

实验名称: 生产者和消费者问题 

学          号:                    

学生姓名:                    

班          级:                     

指导教师:                     

评             分:                    

实验日期:2012年    10月    22 日

1、实验目的:  

掌握基本的同步互斥算法,理解生产者和消费者模型。

了解windows 2000/XP中多线程的并发执行机制,线程间的同步和互斥。

学习使用windows 2000/XP中基本的同步对象,掌握相应的API。

2、实验要求

(1)创建生产和消费线程

在windows2000环境下,创建一个控制台程序,在此进程中创建n个线程来模拟生产者或消费者。这些线程的信息由我们在本程序定义的“测试用例文件”中予以制定。该文件的格式如下:

3

1P  3

2P  4

3C  4  1

4P  2

5C  3  1  2  4

(2)生产和消费的规则

a.共享缓冲区存在空闲空间时,生产者即可用共享缓冲区。

b.只有当所有的消费者需求都被满足以后,该产品所在的共享缓冲区才能被释放,并作为空闲空间允许心的生产者适用。

c.每个消费者线程的各个消费需求之间存在先后顺序。

d.在每个县城发出读写操作申请、开始读写操作和结束读写操作时分别显示一行提示信息。

3、实验环境

硬件: CPU :AMD QL 内存: 2GB显卡:ATI 4570硬盘:日立250G

软件:Windows 2000/XP。     开发工具:VC++6.0。

4、实验内容

1)实现原理

a.生产者和消费者模型

b.同步对象

c.CreateThread的用法

功能:本API创建一个在调用进程的地址空间中执行的线程。

格式:

HANDLE CreateThread(

  LPSECURITY_ATTRIBUTES lpThreadAttributes,

  DWORD dwStackSize,

  LPTHREAD_START_ROUTINE lpStartAddress,

  LPVOID lpParameter,

  DWORD dwCreationFlags,

  LPDWORD lpThreadId

);

d.CreateMutex的用法

功能:本API产生一个命名的或者匿名的互斥量对象。

格式:

HANDLE CreateMutex(

  LPSECURITY_ATTRIBUTESlpMutexAttributes, // 指向安全属性的指针

  BOOLbInitialOwner, // 初始化互斥对象的所有者

  LPCTSTRlpName // 指向互斥对象名的指针

  );

e.CreateSemaphore的用法

功能:本API创建一个命名的或者匿名的信号量对象。

格式:

HANDLE CreateSemaphore(

  LPSECURITY_ATTRIBUTESlpSemaphoreAttributes, // SD

  LONGlInitialCount, // initial count

  LONGlMaximumCount, // maximum count

  LPCTSTRlpName // object name

  );

f.WaitForSingleObject的用法

功能:本API使程序处于等待状态,直到信号hHandle出现或者超出规定的等待最长时间,信号量出现指信号量大于或等于1。

格式:DWORD WaitForSingleObject(

  HANDLE hHandle,

  DWORD dwMilliseconds

  );

g.InitializeCriticalSection的用法

功能: 该函数初始化临界区对象。

格式:

VOID  InitializeCriticalSection(

LPCRITICAL_SECTION lpCriticalSection 

);

h.ReleaseMutex的用法

功能:用来打开互斥锁,即将互斥量加1,。成功调用则返回0。

格式:BOOL  ReleaseMutex (

HANDLE  hMutex

 );

i.EnterCriticalSection 的用法:

功能:用于等待之的呢过临界区对象的所有权。

格式:

VOID  EnterCriticalSection(

   LPCRITICAL_SECTION lpCriticalSection

  );

j.LeaveCriticalSection的用法

功能:释放指定临界区对象的所有权。

格式:

VOID  LeaveCriticalSection(

   LPCRITICAL_SECTION lpCriticalSection

  );

2)程序结构

3)数据结构

(1)用一个整型数组Buffer_Critical来代表缓冲区。不管是生产产品还是对已有产品的消费都需要访问该组缓冲区。

 (2)在程序中用一个自定义结构Threadlnfo记录一条线程的信息,即将测试用例文件中的一行信息记录下来,用于程序创建相应的生产者或者消费者。由于要创建多个线程,所以程序中使用了一个Threadlnfo结构的数组Thread lnfo。

 (3)在实现本程序的消费生产模型时,具体地通过如下同步对象实现互斥:一个互斥量h_mutex,以实现生产者在查询和保留缓冲区内的下一个空位置时进行互斥。每一个生产者用一个信号量与其消费者同步,通过设置h _Semaphore[MAXTHREAD_NUM]信号量数组实现,该组信号量用于表示相应产品已生产。同时用一个表示空缓冲区数目的信号量empty semaphore进行类似的同步,指示缓冲区中是否存在空位置,以便开始生产下一个产品。每一个缓冲区用一个同步对象实现该缓冲区上消费者之间的互斥,这通过设置临界区对象数组PC_Critical[MAX_BUFFER_NUM]实现。

4)实现步骤

(1)打开VC,选择菜单项文件->新建,选择工程选项卡并建立一个名为R-WP1的Win32 console Application工程。

(2)在工程中创建源文件R-WP1.:选择菜单项文件->新建,选择文件选项卡并建立一个名为R-WP1.cpp的C++ Source Files文件,进行编译间接,得到R-WP1.exe程序。

(3)打开工程目录下的debug,再打开test.txt,输入实验数据,并保存。

(4)最后在进行编译连接。并把实验结果截图保存。

5、实验测试及分析:

结果分析:

1、在每个程序中坐须先做P(mutex),后做V(mutex),二者要成对出现。夹在二者中间的代码段就是该进程的临界区。

2、对同步信号量full和empty的P,V操作同样必须成对出现,但它们分别位于不同的程序中。

3、无论在生产者进程中还是在消费者进程中,两个P操作的次序不能颠倒:应先执行同 步信号量的P操作,然后执行互斥信号量的P操作。否则可能造成进程死锁。

6、实验心得体会

1)在添加test.txt文件时,需在R-WP1及debug文件夹下分别储存才能实现程序正常运行。

2)使用vc++6.0创建工程,应当针对程序选择相应的工程类型,例如基于MFC的: MFC AppWizard(exe),或者基于控制台的:Win32 Console Application,这两种是编写普通程序时最常用。

3)学会用vc++6.0编写使用系统c语言程序,基本功不扎实,程序输入不够细心。

附录:源代码

#include

#include

#include

#include

#include

#define MAX_BUFFER_NUM 10

#define INTE_PER_SEC 1000

#define MAX_THREAD_NUM 

struct ThreadInfo

{

 int serial;      

 char entity;          

 double delay;      

 int thread_request[MAX_THREAD_NUM];  

 int n_request;       

};

CRITICAL_SECTION PC_Critical[MAX_BUFFER_NUM]; 

int         Buffer_Critical[MAX_BUFFER_NUM]; 

HANDLE    h_Thread[MAX_THREAD_NUM];  

ThreadInfo Thread_Info[MAX_THREAD_NUM];  

HANDLE empty_semaphore;      

HANDLE h_mutex;        

DWORD  n_Thread = 0;         

DWORD  n_Buffer_or_Critical;        

HANDLE h_Semaphore[MAX_THREAD_NUM]; 

void  Produce(void *p);

void  Consume(void *p); 

bool  IfInOtherRequest(int);

int   FindProducePositon();

int   FindBufferPosition(int);

int    main(void)

{

 DWORD  wait_for_all;

 ifstream inFile;

for(int i=0;i< MAX_BUFFER_NUM;i++)

  Buffer_Critical[i] = -1;    

for(int j=0;j for(int k=0;k   Thread_Info[j].thread_request[k] = -1;

  Thread_Info[j].n_request = 0;

 }

for(i =0;i< MAX_BUFFER_NUM;i++)

  InitializeCriticalSection(&PC_Critical[i]);

 inFile.open("test.txt");

inFile >> n_Buffer_or_Critical;

 inFile.get();

 printf("输入文件是:\\n");

 printf("%d \\n",(int) n_Buffer_or_Critical);

 while(inFile){

inFile >> Thread_Info[n_Thread].serial;

inFile >> Thread_Info[n_Thread].entity;

inFile >> Thread_Info[n_Thread].delay;

  char c;

  inFile.get(c);

  while(c!='\\n'&& !inFile.eof()){

inFile>>

  Thread_Info[n_Thread].thread_request[Thread_Info

[n_Thread].n_request++];

   inFile.get(c); 

  }

  n_Thread++;

 }  

for(j=0;j<(int) n_Thread;j++){

  int    Temp_serial  = Thread_Info[j].serial;

  char   Temp_entity  = Thread_Info[j].entity;

  double Temp_delay   = Thread_Info[j].delay;

  printf(" \\n thread%2d  %c  %f  ",Temp_serial,Temp_entity,Temp_delay);

  int Temp_request = Thread_Info[j].n_request;

for(int k=0;k   printf(" %d    ", Thread_Info[j].thread_request[k]);

cout< }

 printf("\\n\\n");

 empty_semaphore=CreateSemaphore

(NULL,n_Buffer_or_Critical,n_Buffer_or_Critical,

          "semaphore_for_empty");

 h_mutex = CreateMutex(NULL,FALSE,"mutex_for_update");

for(j=0;j<(int)n_Thread;j++){

  std::string lp ="semaphore_for_produce_";

  int temp =j;

  while(temp){

  char c = (char)(temp%10);

  lp+=c;

  temp/=10;

  }

  h_Semaphore[j+1]=CreateSemaphore(NULL,0,n_Thread,lp.c_str());    

 }

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

  if(Thread_Info[i].entity =='P')

   h_Thread[i]= CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(Produce),

         &(Thread_Info[i]),0,NULL);

  else

     h_Thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(Consume),

        &(Thread_Info[i]),0,NULL);

 }

 wait_for_all = WaitForMultipleObjects(n_Thread,h_Thread,TRUE,-1);

 printf(" \\n \\nALL Producer and consumer have finished their work. \\n");

 printf("Press any key to quit!\\n");

 _getch();

 return 0;

}

bool IfInOtherRequest(int req)

{

for(int i=0;i for(int j=0;j   if(Thread_Info[i].thread_request[j] == req)

    return TRUE;

 return FALSE;

}

int FindProducePosition()

{

 int EmptyPosition;

for (int i =0;i  if(Buffer_Critical[i] == -1){

   EmptyPosition = i;

   Buffer_Critical[i] = -2;

   break;

  }

 return  EmptyPosition;

}

int FindBufferPosition(int ProPos)

{

 int TempPos;

for (int i =0 ;i  if(Buffer_Critical[i]==ProPos){

   TempPos = i;

   break;

  }

 return TempPos;

}

void Produce(void *p)

{

 DWORD wait_for_semaphore,wait_for_mutex,m_delay;

 int  m_serial;

m_serial = ((ThreadInfo*)(p))->serial;

m_delay = (DWORD)(((ThreadInfo*)(p))->delay *INTE_PER_SEC);

 Sleep(m_delay);

 printf("Producer %2d sends the produce require.\\n",m_serial);

 wait_for_semaphore =  WaitForSingleObject(empty_semaphore,-1);

 wait_for_mutex  = WaitForSingleObject(h_mutex,-1);

 int  ProducePos = FindProducePosition();

    ReleaseMutex(h_mutex);

 printf("Producer %2d begin  to produce at position %2d.\\n",m_serial,ProducePos);

 Buffer_Critical[ProducePos] = m_serial;

 printf("Producer %2d finish producing :\\n ",m_serial);

 printf("  position[ %2d ]:%3d \\n" ,ProducePos,Buffer_Critical

[ProducePos]);

 ReleaseSemaphore(h_Semaphore[m_serial],n_Thread,NULL);

}

void Consume(void * p)

{

 DWORD wait_for_semaphore,m_delay;

 int m_serial,m_requestNum;         

 int m_thread_request[MAX_THREAD_NUM];

m_serial = ((ThreadInfo*)(p))->serial;

m_delay = (DWORD)(((ThreadInfo*)(p))->delay *INTE_PER_SEC);

m_requestNum = ((ThreadInfo *)(p))->n_request;

for (int i = 0;i m_thread_request[i] = ((ThreadInfo*)(p))->thread_request[i];

 Sleep(m_delay); 

for(i =0;i   printf("Consumer %2d request to consume %2d product\\n",m_serial,m_thread_request[i]);

   wait_for_semaphore=WaitForSingleObject(h_Semaphore[m_thread_request[i]],-1); 

   int BufferPos=FindBufferPosition(m_thread_request[i]);   

   EnterCriticalSection(&PC_Critical[BufferPos]);

   printf("Consumer%2d begin to consume %2d product \\n",m_serial,m_thread_request[i]);

((ThreadInfo*)(p))->thread_request[i] =-1;

  if(!IfInOtherRequest(m_thread_request[i])){

  Buffer_Critical[BufferPos] = -1;

  printf("Consumer%2d finish consuming %2d:\\n ",m_serial,m_thread_request[i]);

  printf("  position[ %2d ]:%3d \\n" ,BufferPos,Buffer_Critical[BufferPos]);

  ReleaseSemaphore(empty_semaphore,1,NULL);

   }  

   else{

printf("Consumer %2d finish consuming product %2d\\n ",m_serial,m_thread_request[i]);

   }

   LeaveCriticalSection(&PC_Critical[BufferPos]);

 }

}下载本文

显示全文
专题