生产者/消费者问题在windows2000下的实现

一、问题描述

生产者-消费者问题是一个经典的进程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制。本作业要求设计在同一个进程地址空间内执行的两个线程。生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。

 

二、实现代码

0000    #include <windows.h>
0001    #include <iostream>
0002    
0003    const unsigned short SIZE_OF_BUFFER = 10;   //缓冲区长度
0004    unsigned short ProductID = 0;               //产品号
0005    unsigned short ConsumeID = 0;               //将被消耗的产品号
0006    unsigned short in = 0;                      //产品进缓冲区时的下标
0007    unsigned short out = 0;                     //产品出缓冲区时的下标
0008    
0009    int g_buffer[SIZE_OF_BUFFER];               //缓冲区是个循环队列
0010    bool g_continue = true;                     //控制程序结束
0011    HANDLE g_hMutex;                            //用于线程间的互斥
0012    HANDLE g_hFullItems;                        //缓冲区中被占用的项
0013    HANDLE g_hEmptyItems;                       //缓冲区中的空项
0014    
0015    DWORD WINAPI Producer(LPVOID);              //生产者线程
0016    DWORD WINAPI Consumer(LPVOID);              //消费者线程
0017    
0018    int main()
0019    {
0020        //创建各个互斥信号
0021        g_hMutex = CreateMutex(NULL,FALSE,NULL);
0022        g_hFullItems = CreateSemaphore(NULL,0,SIZE_OF_BUFFER,NULL);
0023        g_hEmptyItems = CreateSemaphore(NULL,SIZE_OF_BUFFER,
0024                                        SIZE_OF_BUFFER,NULL);
0025    
0026        //缓冲区初始化
0027        for (int i = 0; i< SIZE_OF_BUFFER;++i){
0028            g_buffer[i] = -1;   //当值为-1时该项为空
0029        }
0030    
0031        //调整下面的数值,可以发现,当生产者个数多于消费者个数时,
0032        //生产速度快,生产者经常等待消费者;反之,消费者经常等待
0033        const unsigned short PRODUCERS_COUNT = 3;       //生产者的个数
0034        const unsigned short CONSUMERS_COUNT = 1;       //消费者的个数
0035    
0036        //总的线程数
0037        const unsigned short THREADS_COUNT = PRODUCERS_COUNT+CONSUMERS_COUNT;
0038    
0039        HANDLE hThreads[THREADS_COUNT];     //各线程的handle
0040        DWORD producerID[PRODUCERS_COUNT];  //生产者线程的标识符
0041        DWORD consumerID[CONSUMERS_COUNT];  //消费者线程的标识符
0042    
0043        //创建生产者线程
0044        for (int i=0;i<PRODUCERS_COUNT;++i){
0045            hThreads[i]
0046                =CreateThread(NULL,0,Producer,NULL,0,&producerID[i]);
0047            if (hThreads[i]==NULL) return -1;
0048        }
0049        //创建消费者线程
0050        for (int i=0;i<CONSUMERS_COUNT;++i){
0051            hThreads[PRODUCERS_COUNT+i]
0052                =CreateThread(NULL,0,Consumer,NULL,0,&consumerID[i]);
0053            if (hThreads[i]==NULL) return -1;
0054        }
0055    
0056        while(g_continue){
0057            if(getchar()){  //按回车后终止程序运行
0058                g_continue = false;
0059            }
0060        }
0061    
0062        return 0;
0063    }
0064    
0065    //生产一个产品。简单模拟了一下,仅输出新产品的ID号
0066    void Produce()
0067    {
0068        std::cout << "Producing " << ++ProductID << " ... ";
0069        std::cout << "Succeed" << std::endl;
0070    }
0071    
0072    //把新生产的产品放入缓冲区
0073    void Append()
0074    {
0075        std::cout << "Appending a product ... ";
0076        g_buffer[in] = ProductID;
0077        in = (in+1)%SIZE_OF_BUFFER;
0078        std::cout << "Succeed" << std::endl;
0079    
0080        //输出缓冲区当前的状态
0081        for (int i=0;i<SIZE_OF_BUFFER;++i){
0082            std::cout << i <<": ";
0083            if (g_buffer[i]==-1)
0084                std::cout << "null";
0085            else
0086                std::cout << g_buffer[i];
0087            if (i==in) std::cout << '/t' << " <-- 生产";
0088            if (i==out) std::cout << '/t' << " <-- 消费";
0089            std::cout << std::endl;
0090        }
0091    }
0092    
0093    //从缓冲区中取出一个产品
0094    void Take()
0095    {
0096        std::cout << "Taking a product ... ";
0097        ConsumeID = g_buffer[out];
0098        g_buffer[out]= -1;
0099        out = (out+1)%SIZE_OF_BUFFER;
0100        std::cout << "Succeed" << std::endl;
0101    
0102        //输出缓冲区当前的状态
0103        for (int i=0;i<SIZE_OF_BUFFER;++i){
0104            std::cout << i <<": ";
0105            if (g_buffer[i]==-1)
0106                std::cout << "null";
0107            else
0108                std::cout << g_buffer[i];
0109            if (i==in) std::cout << '/t' << " <-- 生产";
0110            if (i==out) std::cout << '/t' << " <-- 消费";
0111            std::cout << std::endl;
0112        }
0113    }
0114    
0115    //消耗一个产品
0116    void Consume()
0117    {
0118        std::cout << "Consuming " << ConsumeID << " ... ";
0119        std::cout << "Succeed" << std::endl;
0120    }
0121    
0122    //生产者
0123    DWORD  WINAPI Producer(LPVOID lpPara)
0124    {
0125        while(g_continue){
0126            WaitForSingleObject(g_hEmptyItems,INFINITE);
0127            WaitForSingleObject(g_hMutex,INFINITE);
0128            Produce();
0129            Append();
0130            Sleep(1500);
0131            ReleaseMutex(g_hMutex);
0132            ReleaseSemaphore(g_hFullItems,1,NULL);
0133        }
0134        return 0;
0135    }
0136    
0137    //消费者
0138    DWORD  WINAPI Consumer(LPVOID lpPara)
0139    {
0140        while(g_continue){
0141            WaitForSingleObject(g_hFullItems,INFINITE);
0142            WaitForSingleObject(g_hMutex,INFINITE);
0143            Take();
0144            Consume();
0145            Sleep(1500);
0146            ReleaseMutex(g_hMutex);
0147            ReleaseSemaphore(g_hEmptyItems,1,NULL);
0148        }
0149        return 0;
0150    }
0151    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
生产者消费者问题是一个经典的同步问题,用于描述多个线程之间的生产和消费关系。在Windows操作系统中,可以使用Windows API提供的信号量机制来实现生产者消费者问题的解决方案。 下面是一个使用C语言实现Windows生产者消费者问题的示例代码: ```c #include <windows.h> #include <stdio.h> #define BUFFER_SIZE 10 #define PRODUCER_LOOP 100 #define CONSUMER_LOOP 100 int buffer[BUFFER_SIZE]; int in = 0; int out = 0; int count = 0; HANDLE hSemEmpty, hSemFull, hMutex; DWORD WINAPI producer(LPVOID lpParam) { int i, data; for (i = 0; i < PRODUCER_LOOP; i++) { data = i; WaitForSingleObject(hSemEmpty, INFINITE); WaitForSingleObject(hMutex, INFINITE); buffer[in] = data; in = (in + 1) % BUFFER_SIZE; count++; printf("Producer %d produced data %d\n", GetCurrentThreadId(), data); ReleaseMutex(hMutex); ReleaseSemaphore(hSemFull, 1, NULL); } return 0; } DWORD WINAPI consumer(LPVOID lpParam) { int i, data; for (i = 0; i < CONSUMER_LOOP; i++) { WaitForSingleObject(hSemFull, INFINITE); WaitForSingleObject(hMutex, INFINITE); data = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; printf("Consumer %d consumed data %d\n", GetCurrentThreadId(), data); ReleaseMutex(hMutex); ReleaseSemaphore(hSemEmpty, 1, NULL); } return 0; } int main() { HANDLE hProducer[2], hConsumer[2]; DWORD producerId[2], consumerId[2]; hSemEmpty = CreateSemaphore(NULL, BUFFER_SIZE, BUFFER_SIZE, NULL); hSemFull = CreateSemaphore(NULL, 0, BUFFER_SIZE, NULL); hMutex = CreateMutex(NULL, FALSE, NULL); hProducer[0] = CreateThread(NULL, 0, producer, NULL, 0, &producerId[0]); hProducer[1] = CreateThread(NULL, 0, producer, NULL, 0, &producerId[1]); hConsumer[0] = CreateThread(NULL, 0, consumer, NULL, 0, &consumerId[0]); hConsumer[1] = CreateThread(NULL, 0, consumer, NULL, 0, &consumerId[1]); WaitForMultipleObjects(4, hProducer, TRUE, INFINITE); WaitForMultipleObjects(2, hConsumer, TRUE, INFINITE); CloseHandle(hSemEmpty); CloseHandle(hSemFull); CloseHandle(hMutex); return 0; } ``` 在这个例子中,定义了一个大小为10的缓冲区,两个生产者线程和两个消费者线程。生产者线程循环100次,每次产生一个数据并将其存入缓冲区消费者线程循环100次,每次从缓冲区中取出一个数据进行消费。 使用Windows API提供的CreateSemaphore、WaitForSingleObject和ReleaseSemaphore函数实现信号量机制,使用CreateMutex函数实现互斥锁机制。 需要注意的是,在生产者消费者线程中使用WaitForSingleObject和ReleaseSemaphore函数需要注意顺序,不然会导致线程死锁或者数据混乱的情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值