生产者消费者问题——C++ windows版 多生产者多消费者的队列实现
2014-06-09 23:51
561 查看
最进要写一个多线程加载资源的资源管理器(ResourceManager)和多线程音频解码器(MultiThread Decoder)。因为距最近一次用到多线程放下好久了,所以今天把生产者消费者问题练一下手。
为什么选择生产者消费者问题,因为他比较接近资源管理器和多线程音频解码器的原型。
比如,对于音频解码器,音频线程去流式的解码一段MP3格式的内存,就类似生产者生产产品的过程;而音频播放API(如OpenAL,OpenSL)通常需要的是PCM数据,也就是生产者生产的产品,所以播放逻辑充当消费者的角色,典型的生产者消费者问题。
再对于资源管理器,加载Mesh和Texture类似生产单个Resource的过程,而相应的渲染逻辑去使用资源就相当于消费资源的过程,但不同的是最后当不再使用这个资源的时候,这个资源才会被释放,而非使用一次。
今天抽时间,写了一个C++ windows版 多生产者多消费者的队列实现,pthread版估计等需要做跨平台的时候再做,如果想方便直接用OpenMP或者TBB也是可以的,但是对于轻量级引擎,自己实现资源加载器完全足够了。
为什么选择生产者消费者问题,因为他比较接近资源管理器和多线程音频解码器的原型。
比如,对于音频解码器,音频线程去流式的解码一段MP3格式的内存,就类似生产者生产产品的过程;而音频播放API(如OpenAL,OpenSL)通常需要的是PCM数据,也就是生产者生产的产品,所以播放逻辑充当消费者的角色,典型的生产者消费者问题。
再对于资源管理器,加载Mesh和Texture类似生产单个Resource的过程,而相应的渲染逻辑去使用资源就相当于消费资源的过程,但不同的是最后当不再使用这个资源的时候,这个资源才会被释放,而非使用一次。
今天抽时间,写了一个C++ windows版 多生产者多消费者的队列实现,pthread版估计等需要做跨平台的时候再做,如果想方便直接用OpenMP或者TBB也是可以的,但是对于轻量级引擎,自己实现资源加载器完全足够了。
#include <Windows.h> #include <map> #include <queue> CRITICAL_SECTION g_cs; // mutex HANDLE g_hEmptyBufferSemaphore; HANDLE g_hFullBufferSemaphore; #define INVALID -1 #define PRODUCER 5 #define CUSTOMER 5 #define NUM_COUNT 8 #define BUFF_SIZE 4 static std::queue<int> bufferQueue; static std::map< DWORD,int > countMap; bool ProducerFinish = false; //设置控制台输出颜色 BOOL SetConsoleColor(WORD wAttributes) { HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); if (hConsole == INVALID_HANDLE_VALUE) return FALSE; return SetConsoleTextAttribute(hConsole, wAttributes); } DWORD WINAPI ProducerFunc(LPVOID param) { while(true) { WaitForSingleObject( g_hEmptyBufferSemaphore, INFINITE); EnterCriticalSection(&g_cs); DWORD threadId = GetCurrentThreadId(); if(countMap.find(threadId) == countMap.end()) countMap[threadId] = 0; int productID = ++countMap[threadId]; bufferQueue.push( productID); printf("生产者%d , 生产%d\n", threadId, productID); if( productID == NUM_COUNT ) { SetConsoleColor(FOREGROUND_RED); printf("生产者%d生产完毕\n",GetCurrentThreadId()); SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); LeaveCriticalSection(&g_cs); ReleaseSemaphore(g_hFullBufferSemaphore, 1, NULL); break; } LeaveCriticalSection(&g_cs); ReleaseSemaphore(g_hFullBufferSemaphore, 1, NULL); } return NULL; } DWORD WINAPI CustomerFunc(LPVOID param) { while (true) { WaitForSingleObject( g_hFullBufferSemaphore, INFINITE); EnterCriticalSection(&g_cs); int buffer = -1; if(!bufferQueue.empty()) { buffer = bufferQueue.front(); bufferQueue.pop(); } if(buffer != INVALID ) printf("消费者%d ,消费%d\n", GetCurrentThreadId() , buffer); if( bufferQueue.empty() && ProducerFinish) { printf("消费者%d 结束\n",GetCurrentThreadId()); LeaveCriticalSection(&g_cs); // 通知其他消费者可以结束了 ReleaseSemaphore( g_hFullBufferSemaphore, 1, NULL); break; } LeaveCriticalSection(&g_cs); ReleaseSemaphore( g_hEmptyBufferSemaphore, 1, NULL); } return NULL; } int _tmain(int argc, _TCHAR* argv[]) { InitializeCriticalSection(&g_cs); g_hEmptyBufferSemaphore = CreateSemaphore( NULL, 4, 4, NULL); g_hFullBufferSemaphore = CreateSemaphore( NULL, 0, 4, NULL); HANDLE producerThreads[PRODUCER]; HANDLE customerThreads[CUSTOMER]; // producer for (int i = 0; i < PRODUCER; ++i) { producerThreads[i] = CreateThread( NULL, 0, ProducerFunc, NULL, NULL, NULL); } // customers for (int i = 0; i < CUSTOMER; ++i) customerThreads[i] = CreateThread( NULL, 0, CustomerFunc, NULL, NULL, NULL); WaitForMultipleObjects( PRODUCER, producerThreads, TRUE, INFINITE); ProducerFinish = true; WaitForMultipleObjects( CUSTOMER, customerThreads, TRUE, INFINITE); for (int i = 0; i < PRODUCER; ++i) CloseHandle(producerThreads[i]); for (int i = 0; i < CUSTOMER; ++i) CloseHandle(customerThreads[i]); CloseHandle(g_hEmptyBufferSemaphore); CloseHandle(g_hFullBufferSemaphore); DeleteCriticalSection(&g_cs); countMap.clear(); return 0; }
相关文章推荐
- linux下c++实现简单的生产者消费者队列模式
- boost c++ lib on linux(4) - thread同步条件变量学习——生产者消费者队列
- boost::condition_variable 设计c++ 生产者消费者队列
- 珍藏好料开源放送: windows平台一个高性能、通用型的C++生产者/消费者架构模板
- 通过阻塞队列实现生产者消费者模型
- java消费者生产者模式及JDK之阻塞队列LinkedBlockingQueue实现
- LinuxC/C++编程基础(8) 基于条件变量实现生产者与消费者的实例
- 实现一个生产者消费者队列
- boost::condition_variable 设计c++ 生产者消费者队列
- python使用队列实现生产者消费者
- 使用阻塞队列实现生产者和消费者问题
- 用C++实现多个生产者 和多个消费者之间的同步
- 生产者和消费者多线程同步,C++实现
- [实现一个队列]一个生产者线程将int类型的数入列,一个消费者线程将int类型的数出列
- 线程池的实现(生产者消费者),借助队列实现
- 每天学习一算法系列(31)(实现一个队列,队列的应用场景为:一个生产者线程将int 类型的数入列,一个消费者线程将int 类型的数出列)
- boost::condition_variable 设计c++ 生产者消费者队列
- 用生产者消费者模型实现的线程安全环形队列
- Java阻塞队列BlockingQueue实现生产者消费者-只有代码-不讲原理
- 多线程用互斥锁和条件变量实现生产者和消费者-------循环任务队列