生产者消费者多缓冲区实现
2015-01-13 19:19
295 查看
#include<stdio.h> #include<Windows.h> #include<process.h> int gBuffer=0;//全局变量,缓冲区 HANDLE g_EventBufferEmpty,g_EventBufferFull; const int END_PRODUCE_NUMBER=10; //生产者线程 DWORD ProducerThread(PVOID pm) { for(int i=1;i<=END_PRODUCE_NUMBER;i++) { ::WaitForSingleObject(g_EventBufferEmpty,INFINITE); gBuffer=i; printf("生产者放入数据%d\n",gBuffer); ::SetEvent(g_EventBufferFull); } return 0; } //消费者线程 DWORD ConsumerThread(PVOID pm) { while(gBuffer!=END_PRODUCE_NUMBER) { //等待生产者线程写入数据 ::WaitForSingleObject(g_EventBufferFull,INFINITE); printf("消费者从缓冲区中取出数据%d\n",gBuffer); SetEvent(g_EventBufferEmpty); } return 0; } int main() { g_EventBufferEmpty=CreateEvent(NULL,false,TRUE,NULL); g_EventBufferFull=CreateEvent(NULL,false,false,NULL); HANDLE hThread[2]={NULL}; DWORD ProduceID; DWORD ConsumerID; hThread[0]=::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ProducerThread,NULL,0,&ProduceID); hThread[1]=::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ConsumerThread,NULL,0,&ConsumerID); ::WaitForMultipleObjects(2,hThread,true,INFINITE); CloseHandle(hThread[0]); CloseHandle(hThread[1]); CloseHandle(g_EventBufferEmpty); CloseHandle(g_EventBufferFull); }
PS:在但缓冲区的环境下,我们只需要两个互斥变量,一个用来通知消费者消费gEventBufferFull,一个用于通知生产者生产gEventBufferEmpty,这样我们就可以实现了,而在多缓冲区的环境下使用互斥变量则有写捉襟见肘,而是需要使用可以计数的信号量来进行缓冲区的作用代码如下:
//如果有两个缓冲区多个生产者,多个消费者呢? #include<Windows.h> #include<iostream> #include<process.h> #include<vector> using namespace std; const int END_PRODUCE_NUMBER=8; const int BUFFER_SIZE=4; int g_i=0,g_j=0; int gBuffer[BUFFER_SIZE]={0}; //设置信号量和关键段 CRITICAL_SECTION g_cs; HANDLE g_SemphBufferEmpty=0,g_SemphBufferFull=0; int mm[4]={0}; int a=0; //生产者线程 DWORD Produce(PVOID pm) { for(int i=1;i<=END_PRODUCE_NUMBER;i++) { ::WaitForSingleObject(g_SemphBufferEmpty,INFINITE); //互斥访问的代码段 ::EnterCriticalSection(&g_cs); if(mm[g_i]!=1) { gBuffer[g_i]=i; cout<<"生产者线程放入第"<<g_i<<"个缓冲池中的数据:"<<gBuffer[g_i]<<endl; mm[g_i]=1; } g_i=(1+g_i)%BUFFER_SIZE; ::LeaveCriticalSection(&g_cs); ::ReleaseSemaphore(g_SemphBufferFull,1,NULL); } cout<<"生产者完成任务\n"; a=1; return 0; } //消费者线程 DWORD Consumer(LPVOID pm) { //只要有我们就可以进行消费 while(TRUE) { ::WaitForSingleObject(g_SemphBufferFull,INFINITE); ::EnterCriticalSection(&g_cs); //取出第一个可用数据 for(int i=0;i<4;i++) { if(mm[i]==1) { cout<<"消费者线程取出第"<<i<<"个缓冲池中的数据:"<<gBuffer[i]<<endl; mm[i]=0; break; } } ::LeaveCriticalSection(&g_cs); ::ReleaseSemaphore(g_SemphBufferEmpty,1,NULL); ::Sleep(100); int hh=0; for(int i=0;i<4;i++) { if(mm[i]==0) hh++; } if(hh==4&&a==1) { break; } } cout<<"消费者完成任务"<<endl; return 0; } int main() { //开始初始化代码段 ::InitializeCriticalSection(&g_cs); //初始化信号量 g_SemphBufferEmpty=::CreateSemaphoreA(NULL,4,4,NULL); g_SemphBufferFull=::CreateSemaphoreA(NULL,0,4,NULL); HANDLE hThread[3]; DWORD ThreadId; hThread[0]=::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Consumer,NULL,0,&ThreadId); hThread[1]=::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Produce,NULL,0,&ThreadId); hThread[2]=::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Produce,NULL,0,&ThreadId); ::WaitForMultipleObjects(3,hThread,true,INFINITE); for(int i=0;i<3;i++) { CloseHandle(hThread[i]); } CloseHandle(g_SemphBufferFull); CloseHandle(g_SemphBufferEmpty); ::DeleteCriticalSection(&g_cs); }
思路:主要就是最大值是4的信号量,我们根据这个信号量进行缓冲区的设置除了4个缓冲区gBuffer[4]以外还有一个对着4个缓冲区标志的索引mm[4],如果第i个缓冲区已经被使用那么mm[i]就为1,如果消费者对第j个缓冲区进行了消费,那么mm[j]=0;
每次生产者对缓冲区操作的时候需要检测mm相对应位置上的值是不是0,每次消费者对缓冲区读取的时候需要检测mm对应的值是不是1,这样我们就完成了生产者消费者的线程模型
相关文章推荐
- linux下C语言实现多线程通信—环形缓冲区,可用于生产者(producer)/消费者(consumer)
- 架构设计:生产者/消费者模式 第6页:环形缓冲区的实现
- 异步之生产者消费者模型--同步缓冲区的实现
- 架构设计:生产者/消费者模式 第6页:环形缓冲区的实现
- 架构设计:生产者/消费者模式 第6页:环形缓冲区的实现
- 生产者消费者 多线程 单个缓冲区 Win32API实现
- 架构设计:生产者/消费者模式 第6页:环形缓冲区的实现
- linux下C语言实现多线程通信—环形缓冲区,可用于生产者(producer)/消费者(consumer)【转】
- 生产者/消费者模式 (六) 环形缓冲区的实现
- 架构设计:生产者/消费者模式 第6页:环形缓冲区的实现
- 关于消费者.生产者,缓冲区的简单java实现
- linux下生产者消费者的实现
- 生产者-消费者问题(condition)Java实现
- 多个生产者-一个消费者-进程间同步的例子 - OutputDebugString的实现
- 生产者-消费者问题实现 (linux下C语言)
- .net实现--多线程之生产者/消费者问题
- unix 多进程下的生产者和消费者实现
- 用多线程实现“生产者-消费者问题”(代码+实验报告)
- 用多线程实现“生产者-消费者问题”(代码+实验报告)
- 生产者消费者问题之Java线程实现