生产者消费者问题.docx
《生产者消费者问题.docx》由会员分享,可在线阅读,更多相关《生产者消费者问题.docx(12页珍藏版)》请在冰豆网上搜索。
![生产者消费者问题.docx](https://file1.bdocx.com/fileroot1/2022-10/10/8b04778b-fc6e-4de6-a9d8-21ad05e1ee98/8b04778b-fc6e-4de6-a9d8-21ad05e1ee981.gif)
生产者消费者问题
实训二操作系统中的经典线程同步问题
一、实训目的:
1、通过对“生产者-消费者”问题编程实现,了解线程创建、同步信号量、互斥信号量、临界区的创建和使用。
2、了解线程互斥和同步机制。
3、了解PV原语和信号量在线程互斥和同步机制中的运用。
二、实训环境:
一台PC机/人
三、预习内容:
1、进程的控制。
2、进程同步。
3、本实验内容主要对应于教材第2章中关于进程的各节
四、实训内容:
1、编写进程控制程序并运行,理解进程控制的各操作。
2、生产者和消费者问题,本实验用到几个API函数:
CreatThread,CreatMutex,CreatSemaphore,WaitForSingleObject,ReleaseSemaphore,ReleaseMutex,InitializeCriticalSection,EnterCriticalSection,LeaveCriticalSection
这些函数的作用:
CreatThread:
创建一个线程,该线程在调用进程的地址空间中执
CreatMutex:
产生一个命名的或者匿名的互斥量对象。
WaitForSingleObject(对应p操作)锁上互斥锁,ReleaseMutex(对应v操作)打开互斥锁。
CreateSemaphore:
创建一个命名的或者匿名的信号对象。
信号量可以看作是在互斥量上的一个扩展。
WaitForSingleObject:
使程序处于等待状态,直到信号量(或互斥量)hHandle出现或者超过规定的等待最长时间,信号量出现指信号量大于或等于1,互斥量出现指打开互斥锁。
在返回之前将信号量减1或者锁上互斥锁。
ReleaseSemaphore:
将所指信号量加上指定大小的一个量,执行成功,则返回非0值。
ReleaseMutex:
用来打开互斥量,即将互斥量加1。
成功调用则返回0。
InitializeCriticalSection:
该函数初始化临界区对象。
EnterCriticalSection:
该函数用于等待指定临界区对象的所有权。
当调用线程被赋予所有权时,该函数返回。
LeaveCriticalSection:
该函数释放指定的临界区对象的所有权。
3、测试数据设计及测试结果分析
已知测试用例文件输入的文件时:
5
thread1P5.000000
thread2P4.000000
thread3P2.000000
thread4C6.00000056
thread5P7.000000
thread6P1.000000
thread7C3.000000132
生产者6发送生产请求信号.
生产者6开始在缓冲区0生产产品.
生产者6完成生产过程:
缓冲区【0】:
6
生成者3发送生产请求信号.
生产者3开始在缓冲区1生产产品.
生产者3完成生产过程:
缓冲区【1】:
3
消费者7请求消费1产品
消费者7请求消费1产品
生产者2发送生成者请求信号.
生产者2开始在缓冲区2生产产品
生产者2完成生产过程:
缓冲区【2】:
2
生产者1发送生产请求信号.
生产者1开始在缓冲区3生产产品.
生产者1完成生产过程:
缓冲区【3】:
1
消费者7开始消费1产品
消费者7成功消费1:
缓冲区【3】:
-1
消费者7请求消费3产品
消费者7开始消费3产品
消费者7成功消费3:
缓冲区【1】:
-1
消费者7请求消费2产品
消费者7开始消费2产品
消费者7成功消费2:
缓冲区【2】:
-1
消费者4请求消费5产品
生产者5发送生产请求信号.
生产者5开始在缓冲区1生产产品
生产者5完成生产过程
缓冲区【1】:
5
消费者4请求消费5产品
消费者4请求消费5产品
缓冲区【1】:
-1
消费者4请求消费6产品
消费者4开始消费6产品
消费者4成功消费6:
缓冲区【0】:
-1
五、参考程序
#include
#include
#include
#include
#include
//定义一些常量;
//本程序允许的最大临界区数;
#defineMAX_BUFFER_NUM10
//秒到毫秒的乘法因子;
#defineINTE_PER_SEC1000
//本程序允许的生产和消费线程的总数;
#defineMAX_THREAD_NUM64
//定义一个结构,记录在测试文件中指定的每一个线程的参数
structThreadInfo
{
intserial;//线程序列号
charentity;//是P还是C
doubledelay;//线程延迟
intthread_request[MAX_THREAD_NUM];//线程请求队列
intn_request;//请求个数
};
//全局变量的定义
//临界区对象的声明,用于管理缓冲区的互斥访问;
CRITICAL_SECTIONPC_Critical[MAX_BUFFER_NUM];
intBuffer_Critical[MAX_BUFFER_NUM];//缓冲区声明,用于存放产品;
HANDLEh_Thread[MAX_THREAD_NUM];//用于存储每个线程句柄的数组;
ThreadInfoThread_Info[MAX_THREAD_NUM];//线程信息数组;
HANDLEempty_semaphore;//一个信号量;
HANDLEh_mutex;//一个互斥量;
DWORDn_Thread=0;//实际的线程的数目;
DWORDn_Buffer_or_Critical;//实际的缓冲区或者临界区的数目;
HANDLEh_Semaphore[MAX_THREAD_NUM];//生产者允许消费者开始消费的信号量;
//生产消费及辅助函数的声明
voidProduce(void*p);
voidConsume(void*p);
boolIfInOtherRequest(int);
intFindProducePositon();
intFindBufferPosition(int);
intmain(void)
{
//声明所需变量;
DWORDwait_for_all;
ifstreaminFile;
//初始化缓冲区;
for(inti=0;iBuffer_Critical[i]=-1;
//初始化每个线程的请求队列;
for(intj=0;jfor(intk=0;kThread_Info[j].thread_request[k]=-1;
Thread_Info[j].n_request=0;
}
//初始化临界区;
for(i=0;iInitializeCriticalSection(&PC_Critical[i]);
//打开输入文件,按照规定的格式提取线程等信息;
inFile.open("test1.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;
charc;
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++){
intTemp_serial=Thread_Info[j].serial;
charTemp_entity=Thread_Info[j].entity;
doubleTemp_delay=Thread_Info[j].delay;
printf("\nthread%2d%c%f",Temp_serial,Temp_entity,Temp_delay);
intTemp_request=Thread_Info[j].n_request;
for(intk=0;kprintf("%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");
//下面这个循环用线程的ID号来为相应生产线程的产品读写时所
//使用的同步信号量命名;
for(j=0;j<(int)n_Thread;j++){
std:
:
stringlp="semaphore_for_produce_";
inttemp=j;
while(temp){
charc=(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]=CreateThre