参考地址:http://blog.csdn.net/morewindows/article/details/7577591
生产者消费者问题是一个著名的线程同步问题,该问题描述如下:有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个具有多个缓冲区的缓冲池,生产者将它生产的产品放入一个缓冲区中,消费者可以从缓冲区中取走产品进行消费,显然生产者和消费者之间必须保持同步,即不允许消费者到一个空的缓冲区中取产品,也不允许生产者向一个已经放入产品的缓冲区中再次投放产品。
代码一:1个生产者,1个消费者,1个缓冲区
1 #include <iostream> 2 #include <Windows.h> 3 #include <process.h> 4 using namespace std; 5 /************************************************************************************ 6 7 模拟单个缓冲区的情况 8 9 *************************************************************************************/ 10 const int PRODUCT_NUM = 10; //生产产品个数 11 int g_nBuffer; //缓冲区 12 CRITICAL_SECTION g_cs; 13 HANDLE g_hEventBufferEmpty; 14 HANDLE g_hEventBufferFull; 15 16 //设置控制台文字颜色 17 BOOL SetConsoleColor(WORD wAttributes) 18 { 19 HANDLE hHandle = GetStdHandle(STD_OUTPUT_HANDLE); 20 if (hHandle == INVALID_HANDLE_VALUE) 21 { 22 cout << "GetStdHandle Error!" << endl; 23 return false; 24 } 25 //SetConsoleTitle(L"生产者消费者问题"); 26 return SetConsoleTextAttribute(hHandle, wAttributes); 27 } 28 29 unsigned int WINAPI ProducerThreadFunc(PVOID pParam) 30 { 31 for (int i = 1; i <= PRODUCT_NUM; ++i) 32 { 33 if (i > PRODUCT_NUM) 34 { 35 return 0; 36 } 37 WaitForSingleObject(g_hEventBufferEmpty, INFINITE); 38 EnterCriticalSection(&g_cs); 39 g_nBuffer = i; 40 SetConsoleColor(FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED); 41 cout << "生产者将数据[" << i << "]放入缓冲区!" << endl; 42 LeaveCriticalSection(&g_cs); 43 SetEvent(g_hEventBufferFull); 44 } 45 return 0; 46 } 47 48 unsigned int WINAPI ConsumerThreadFunc(PVOID pParam) 49 { 50 //volatile bool bFlag = true; 51 while(true) 52 { 53 WaitForSingleObject(g_hEventBufferFull, INFINITE); 54 EnterCriticalSection(&g_cs); 55 SetConsoleColor(FOREGROUND_GREEN); 56 cout << "消费者从缓冲区中取出数据[" << g_nBuffer << "]" << endl; 57 SetConsoleColor(FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN); 58 if (g_nBuffer == PRODUCT_NUM) 59 { 60 LeaveCriticalSection(&g_cs); 61 return 0; 62 } 63 Sleep(100); 64 LeaveCriticalSection(&g_cs); 65 SetEvent(g_hEventBufferEmpty); 66 } 67 return 0; 68 } 69 70 int main() 71 { 72 const int nThreadNum = 2; 73 HANDLE hThread[nThreadNum]; 74 g_hEventBufferEmpty = CreateEvent(NULL, false, true, NULL); 75 g_hEventBufferFull = CreateEvent(NULL, false, false, NULL); 76 InitializeCriticalSection(&g_cs); 77 78 cout << "\t\t生产者消费者问题:1生产者,1消费者,1缓冲区" << endl; 79 hThread[0] = (HANDLE)_beginthreadex(NULL, 0, ProducerThreadFunc, NULL, 0, NULL); 80 hThread[1] = (HANDLE)_beginthreadex(NULL, 0, ConsumerThreadFunc, NULL, 0, NULL); 81 WaitForMultipleObjects(nThreadNum, hThread, true, INFINITE); 82 83 CloseHandle(hThread[0]); 84 CloseHandle(hThread[1]); 85 CloseHandle(g_hEventBufferFull); 86 CloseHandle(g_hEventBufferEmpty); 87 DeleteCriticalSection(&g_cs); 88 89 return 0; 90 }
代码二:1个生成者,2个消费者,4个缓冲区
1 #include <iostream> 2 #include <Windows.h> 3 #include <process.h> 4 using namespace std; 5 /************************************************************************************ 6 7 模拟多个缓冲区、多个消费者的情况 8 9 *************************************************************************************/ 10 const int PRODUCT_NUM = 10; //生产产品个数 11 const int BUFFERSIZE = 4; //缓冲区个数 12 int g_nBuffer[BUFFERSIZE]; 13 int g_nProduceCnt; //生产位置 14 int g_nConsumeCnt; //消费位置 15 CRITICAL_SECTION g_cs; 16 HANDLE g_hSemaphoreEmpty; 17 HANDLE g_hSemaphoreFull; 18 19 //设置控制台文字颜色 20 BOOL SetConsoleColor(WORD wAttributes) 21 { 22 HANDLE hHandle = GetStdHandle(STD_OUTPUT_HANDLE); 23 if (hHandle == INVALID_HANDLE_VALUE) 24 { 25 cout << "GetStdHandle Error!" << endl; 26 return false; 27 } 28 //SetConsoleTitle(L"生产者消费者问题"); 29 return SetConsoleTextAttribute(hHandle, wAttributes); 30 } 31 32 unsigned int WINAPI ProducerThreadFunc(PVOID pParam) 33 { 34 for (int i = 1; i <= PRODUCT_NUM; ++i) 35 {//生产者与消费者之间本不应该互斥,但是这里考虑到设置控制台颜色的问题,必须互斥,实际情况这里的互斥条件应该去掉 36 WaitForSingleObject(g_hSemaphoreEmpty, INFINITE); 37 EnterCriticalSection(&g_cs); 38 g_nProduceCnt = (i-1)%BUFFERSIZE; 39 g_nBuffer[g_nProduceCnt] = i; 40 SetConsoleColor(FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED); 41 cout << "生产者[" << GetCurrentThreadId() << "]将数据[" << i << "]放入缓冲区位置[" << g_nProduceCnt << "]" << endl; 42 LeaveCriticalSection(&g_cs); 43 ReleaseSemaphore(g_hSemaphoreFull, 1, NULL); 44 } 45 return 0; 46 } 47 48 unsigned int WINAPI ConsumerThreadFunc(PVOID pParam) 49 { 50 volatile bool bFlag = true; 51 while(bFlag) 52 { 53 WaitForSingleObject(g_hSemaphoreFull, INFINITE); 54 EnterCriticalSection(&g_cs); 55 if (!bFlag) 56 { 57 LeaveCriticalSection(&g_cs); 58 return 0; 59 } 60 SetConsoleColor(FOREGROUND_GREEN); 61 cout << "消费者[" << GetCurrentThreadId() << "]从缓冲区中位置[" << g_nConsumeCnt%BUFFERSIZE << "]取出数据[" <<
g_nBuffer[g_nConsumeCnt%BUFFERSIZE] << "]" << endl; 62 ++g_nConsumeCnt; 63 SetConsoleColor(FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN); 64 if (g_nConsumeCnt == PRODUCT_NUM) 65 { 66 LeaveCriticalSection(&g_cs); 67 bFlag = false; 68 } 69 Sleep(100); 70 LeaveCriticalSection(&g_cs); 71 ReleaseSemaphore(g_hSemaphoreEmpty, 1, NULL); 72 } 73 return 0; 74 } 75 76 int main() 77 { 78 const int nThreadNum = 3; 79 HANDLE hThread[nThreadNum]; 80 81 g_hSemaphoreEmpty = CreateSemaphore(NULL, 4, BUFFERSIZE, NULL); 82 g_hSemaphoreFull = CreateSemaphore(NULL, 0, BUFFERSIZE, NULL); 83 InitializeCriticalSection(&g_cs); 84 85 g_nProduceCnt = 0; 86 g_nConsumeCnt = 0; 87 cout << "\t\t生产者消费者问题:1生产者,2消费者,4缓冲区" << endl; 88 hThread[0] = (HANDLE)_beginthreadex(NULL, 0, ProducerThreadFunc, NULL, 0, NULL); 89 hThread[1] = (HANDLE)_beginthreadex(NULL, 0, ConsumerThreadFunc, NULL, 0, NULL); 90 hThread[2] = (HANDLE)_beginthreadex(NULL, 0, ConsumerThreadFunc, NULL, 0, NULL); 91 WaitForMultipleObjects(nThreadNum, hThread, true, INFINITE); 92 93 for (int i = 0; i < nThreadNum; ++i) 94 CloseHandle(hThread[i]); 95 CloseHandle(g_hSemaphoreFull); 96 CloseHandle(g_hSemaphoreEmpty); 97 DeleteCriticalSection(&g_cs); 98 99 return 0; 100 }
功不成,身已退
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决
2014-12-29 Win32进程创建、进程快照、进程终止用例