生产者和消费者问题

来源:互联网 发布:普通话练习软件 编辑:程序博客网 时间: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;}