并发控制-生产者-消费者问题

来源:互联网 发布:linux oracle em 编辑:程序博客网 时间:2024/06/05 03:37

/*
生产者与消费者问题的实现。
创建一组“生产者”线程和一组“消费者”线程,并建立一个长度为N的缓冲池。
“生产者”向缓冲区输入数据,“消费者”从缓冲区读出数据。
当缓冲区满时,“生产者”必须阻塞,等待“消费者”取走缓冲区数据后将其唤醒。
当缓冲区空时,“消费者”阻塞,等待“生产者”生产了产品后将其唤醒。
用信号量实现“生产者”与“消费者”线程之间的同步。
 
*/
#include <windows.h>
#include <iostream>
#include<cstdio>


const int PCOUNT = 5;                                    //生产者的个数
const int CCOUNT = 5;                                    //消费者的个数
const int N = 8;                                        //缓冲池中缓冲区数量
int ProductID = 0;                                       //生产产品号
int ConsumeID = 0;                                       //消费产品号
int in = 0;    
int out = 0;
int total = 0;                                           //库存量
int Buffer[N];                                                      //缓冲池
int buffer[N];
bool stop = false;    
HANDLE Mutex;                                                       //互斥信号量实现缓冲池的互斥使用       
HANDLE Full;                                                        //缓冲池中满缓冲区的数量
HANDLE Empty;                                                       //缓冲池中空缓冲区的数量

SYSTEMTIME systime;

DWORD WINAPI Producer(LPVOID);                                      //生产者线程
DWORD WINAPI Consumer(LPVOID);                                      //消费者线程

int main()
{
    //创建各个互斥信号
    Mutex = CreateMutex(NULL,FALSE,NULL);
    Full = CreateSemaphore(NULL,N-1,N-1,NULL);
    Empty = CreateSemaphore(NULL,0,N-1,NULL);
 //创建互斥信号量失败
 if (Mutex == NULL)
    {
        printf("CreateMutex error: %d\n", GetLastError());
        return 0;
    }
 //创建Full信号量失败
 if (Full == NULL)
    {
        printf("CreateSemaphoreFull error: %d\n", GetLastError());
        return 0;
    }
 //创建Empty信号量失败
 if (Empty == NULL)
    {
        printf("CreateSemaphoreEmpty error: %d\n", GetLastError());
        return 0;
    }

 HANDLE ProducerThreads[PCOUNT];                                   //生产者线程
 HANDLE ConsumerThreads[CCOUNT];                                   //消费者线程
    DWORD producerID[PCOUNT];                                         //生产者线程的标识符
    DWORD consumerID[CCOUNT];                                         //消费者线程的标识符

    //创建生产者线程
    for (int i=0;i<PCOUNT;++i)
 {
        ProducerThreads[i]=CreateThread(NULL,0,Producer,NULL,0,&producerID[i]);
  if(ProducerThreads[i] == NULL )
  {
            printf("CreateThread error: %d\n", GetLastError());
            return 0;
  }
    }
    //创建消费者线程
    for (i=0;i<CCOUNT;++i)
 {
        ConsumerThreads[i]=CreateThread(NULL,0,Consumer,NULL,0,&consumerID[i]);
        if( ConsumerThreads[i] == NULL)
  {
            printf("CreateThread error: %d\n", GetLastError());
            return 0;
  }
    }

    while(!stop)
 {
        if(getchar())//按回车后终止程序运行
  {
           stop = true;
        }
    }
    return 0;
}

//生产
void Produce()
{
 printf("生产第%d个产品并加入库存中\n",++ProductID );
    Buffer[in] = 1;
    in = (in+1)%N;
   //输出缓冲区当前的状态
 printf("缓冲区当前的状态:");
    for (int i=0;i<N;++i)
 {
        printf("%d",Buffer[i]);
    }
 printf("\n");
 printf("生产者ID:%d\n",GetCurrentThreadId());
 buffer[in-1] = GetCurrentThreadId();
 printf("产品ID:%d\t\t缓冲区ID:%d\n",ProductID,in);
 GetLocalTime(&systime);
 printf("时间:%02d:%02d:%02d\t\t", systime.wHour, systime.wMinute, systime.wSecond);
 printf("当前库存量:%d\n",++total);
 printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
}

//消费
void Consume()
{
 printf("消费第%d个产品并从库存拿出\n",++ConsumeID);
    Buffer[out] = 0;
    out = (out+1)%N;
    //输出缓冲区当前的状态
 printf("缓冲区当前的状态:");
    for (int i=0;i<N;++i)
 {
        printf("%d",Buffer[i]);
    }
 printf("\n");
 printf("消费者ID:%d\n",GetCurrentThreadId());
 printf("产品ID:%d\t\t缓冲区ID:%d\t\t来自生产者ID:%d\n",ConsumeID,out,buffer[out-1]);
 GetLocalTime(&systime);
 printf("时间:%02d:%02d:%02d\t\t", systime.wHour, systime.wMinute, systime.wSecond);
 printf("当前库存量:%d\n",--total);
 printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
}


//生产者
DWORD  WINAPI Producer(LPVOID lpPara)
{
    while(!stop)
 {
        WaitForSingleObject(Full,INFINITE);
        WaitForSingleObject(Mutex,INFINITE);
        Produce();
        Sleep(1000);
        ReleaseMutex(Mutex);
        ReleaseSemaphore(Empty,1,NULL);
    }
    return 0;
}

//消费者
DWORD  WINAPI Consumer(LPVOID lpPara)
{
    while(!stop)
 {
        WaitForSingleObject(Empty,INFINITE);
        WaitForSingleObject(Mutex,INFINITE);
        Consume();
        Sleep(1000);
        ReleaseMutex(Mutex);
        ReleaseSemaphore(Full,1,NULL);
    }
    return 0;
}

原创粉丝点击