生产者和消费者问题
来源:互联网 发布:普通话练习软件 编辑:程序博客网 时间:2024/06/05 20:56
#include <windows.h>#include <stdio.h>#define BUFFER_SIZE 10typedef struct Prodcon{ //position for reading and writing int readpos; int writepos; int buffer[BUFFER_SIZE];//缓冲}Prodcon;bool isOver = false;HANDLE hmutex;HANDLE hfullsemaphore;HANDLE hemptysemaphore;void init(Prodcon * pb){ memset(pb->buffer,0,sizeof(pb->buffer));//内存空间初始化 pb->readpos = 0; pb->writepos = 0;}//store an integer in the buffervoid put(Prodcon* pb,int data){ //等待函数可使线程自愿进入等待状态,直到一个特定的内核对象变为已通知状态为止。 /*DWORD WINAPI WaitForSingleObject( __in HANDLE hHandle, __in DWORD dwMilliseconds ); 参数: hHandle:对象句柄。可以指定一系列的对象 如果dwMilliseconds为INFINITE,对象被触发信号后,函数才会返回。*/ WaitForSingleObject(hemptysemaphore,INFINITE);//缓冲区是否有产品剩余空间 WaitForSingleObject(hmutex,INFINITE);//缓冲区,互斥信号量,是否可进入缓冲区 pb->buffer[pb->writepos] = data; pb->writepos++; pb->writepos %= BUFFER_SIZE; printf("put----第%d个位置的产品\n",pb->writepos); ReleaseMutex(hmutex);//释放缓冲区 ReleaseSemaphore(hfullsemaphore,1,NULL); /* 函数功能:递增信号量的当前资源计数 函数原型: BOOL ReleaseSemaphore( HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount ); 函数说明: 第一个参数是信号量的句柄。 第二个参数表示增加个数,必须大于0且不超过最大资源数量。 第三个参数可以用来传出先前的资源计数,设为NULL表示不需要传出。 注意:当前资源数量大于0,表示信号量处于触发,等于0表示资源已经耗尽故信号量处于末触发。 在对信号量调用等待函数时,等待函数会检查信号量的当前资源计数, 如果大于0(即信号量处于触发状态),减1后返回让调用线程继续执行。 一个线程可以多次调用等待函数来减小信号量。*/}//read an integer from the bufferint get(Prodcon* pb){ int data; WaitForSingleObject(hfullsemaphore,INFINITE);//缓存区是否有产品 WaitForSingleObject(hmutex,INFINITE);//申请进入缓存区 data = pb->buffer[pb->readpos]; pb->readpos ++; pb->readpos %= BUFFER_SIZE; printf("get---第%d个位置的产品\n",pb->readpos); ReleaseMutex(hmutex); ReleaseSemaphore(hemptysemaphore,1,NULL); return data;}DWORD WINAPI produce(LPVOID lppara)//DWORD是数据类型,在这里是返回值。//WINAPI是函数的调用形式,最终就是_stdcall形式,就被调用函数来清理栈中的参数,这种形式是不能实现可变参数的。//LPVOID是一个没有类型的指针,也就是说你可以将LPVOID类型的变量赋值给任意类型的指针{ Prodcon* pb = (Prodcon*)lppara; printf("produce线程已创建\n\n"); while(1) { for(int i=1; i<=50; ++i) { put(pb,i); printf("Thread %d put a data: %d\n\n",GetCurrentThreadId(),i); Sleep(10); //延时函数,producer is fast } isOver = true; break; } return NULL;}DWORD WINAPI consume(LPVOID lppara){ Prodcon* pb = (Prodcon*)lppara; printf("consume线程已创建\n\n"); while(1) { int d = get(pb); printf("Thread %d get data: %d\n\n",GetCurrentThreadId(),d); if(isOver == true && pb->readpos == pb->writepos) { printf("OVER!\n"); break; } Sleep(50); //consumer is slow } return NULL;}int main(){ DWORD writerdata;//unsigned long 32位无符号整数 DWORD readerdata; // DWORD readerdata1; Prodcon pb; init(&pb); hmutex = CreateMutex(NULL,false,NULL); //test produce/consume semaphore trigger /*CreateSemaphore函数: 函数功能:创建信号量 函数原型: HANDLE CreateSemaphore( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName ); 函数说明: 第一个参数表示安全控制,一般直接传入NULL。 第二个参数表示初始资源数量。 第三个参数表示最大并发数量。 第四个参数表示信号量的名称,传入NULL表示匿名信号量。*/ hfullsemaphore = CreateSemaphore(NULL,0,BUFFER_SIZE,NULL); hemptysemaphore = CreateSemaphore(NULL,BUFFER_SIZE,BUFFER_SIZE,NULL); /*function CreateThread( lpThreadAttributes: Pointer; {安全设置} dwStackSize: DWORD; {堆栈大小} lpStartAddress: TFNThreadStartRoutine; {入口函数} lpParameter: Pointer; {函数参数} dwCreationFlags: DWORD; {启动选项 ,若传参为0: 线程建立后立即执行入口函数;} var lpThreadId: DWORD {输出线程 ID } ): THandle; stdcall; {返回线程句柄}*/ /*CreateThread 第三个参数是函数指针, 新线程建立后将立即执行该函数, 函数执行完毕, 系统将销毁此线程从而结束多线程*/ //返回值:返回线程句柄 //“句柄” 类似指针, 但通过指针可读写对象, 通过句柄只是使用对象;// CreateThread(NULL,0,produce,&pb,0,&writerdata); // CreateThread(NULL,0,consume,&pb,0,&readerdata); if(CreateThread(NULL,0,produce,&pb,0,&writerdata)==NULL) return -1; if(CreateThread(NULL,0,consume,&pb,0,&readerdata)==NULL) return -1; char ch; while(1) { ch = getchar(); //press "e" to exit if(ch == 'e') break; } printf("Program ends successfully\n"); CloseHandle(hmutex); CloseHandle(hfullsemaphore); CloseHandle(hemptysemaphore); return 0;}
阅读全文
0 0
- 消费者和生产者问题
- 生产者和消费者问题
- 生产者和消费者问题
- 生产者和消费者问题
- 消费者和生产者问题
- 生产者和消费者问题
- 生产者和消费者问题
- 生产者和消费者问题
- 生产者和消费者问题
- 生产者和消费者问题
- 生产者和消费者问题
- 生产者和消费者问题
- 生产者和消费者问题
- 生产者和消费者问题
- 生产者和消费者问题
- 生产者和消费者问题
- 生产者和消费者问题
- 生产者和消费者问题
- 一位来自停电52个半小时的海妙小可爱的实验一报告
- 文本省略号
- iOS Block传值~demo
- hadoop shell命令详解
- 支付宝芝麻认证接口-扫码方式(芝麻认证接口与之类似)
- 生产者和消费者问题
- C#设计模式(4)——抽象工厂模式
- 九度OJ题目1036:Old Bill
- APPLY运算符
- Android Study Material Design 二 之:这可能是RecyclerView最全解析 初级使用(一)
- C#设计模式(5)——建造者模式(Builder Pattern)
- 抽象类
- 学习笔记-LVS的三种模式以及优缺点
- JavaSE-RxJava2笔记