原作者提供源碼為兩種情況:
第一種:1生產者1消費者1緩衝區
第二種:1生產者 2消費者 4緩衝區
========================下面為修改作者源碼得到的 3個生產者1個消費者4個緩衝區的情況==================
//1生產者 2消費者 4緩衝區 #include <stdio.h> #include <process.h> #include <windows.h> //設定控制台輸出顏色 BOOL SetConsoleColor(WORD wAttributes) { HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); if (hConsole == INVALID_HANDLE_VALUE) return FALSE; return SetConsoleTextAttribute(hConsole, wAttributes); } const int END_PRODUCE_NUMBER = 9; //生產產品個數 const int BUFFER_SIZE = 4; //緩衝區個數 int g_Buffer[BUFFER_SIZE]; //緩衝池 int g_i, g_j; //訊號量與關鍵段 CRITICAL_SECTION g_cs; HANDLE g_hSemaphoreBufferEmpty, g_hSemaphoreBufferFull; int data=0;//生產者線程函數 unsigned int __stdcall ProducerThreadFun(PVOID pM) { //for (int i = 1; i <= END_PRODUCE_NUMBER; i++) //{ while(data<END_PRODUCE_NUMBER){ //等待有空的緩衝區出現 WaitForSingleObject(g_hSemaphoreBufferEmpty, INFINITE); //互斥的訪問緩衝區 EnterCriticalSection(&g_cs); if(data==END_PRODUCE_NUMBER){LeaveCriticalSection(&g_cs);break;}data=data+1; g_Buffer[g_i] = data; //printf("生產者在緩衝池第%d個緩衝區中投放資料%d\n", g_i, g_Buffer[g_i]);printf("編號為%d的生產者在緩衝池中第%d個緩衝區中投放資料%d\n", GetCurrentThreadId(), g_i, g_Buffer[g_i]); g_i = (g_i + 1) % BUFFER_SIZE; LeaveCriticalSection(&g_cs); Sleep(50); //通知消費者有新資料了 ReleaseSemaphore(g_hSemaphoreBufferFull, 1, NULL); }/* } */ printf("生產者完成任務,線程結束運行\n"); return 0; } //消費者線程函數 unsigned int __stdcall ConsumerThreadFun(PVOID pM) { while (true) { //等待非空的緩衝區出現 WaitForSingleObject(g_hSemaphoreBufferFull, INFINITE); //互斥的訪問緩衝區 EnterCriticalSection(&g_cs); SetConsoleColor(FOREGROUND_GREEN); /*printf(" 編號為%d的消費者從緩衝池中第%d個緩衝區取出資料%d\n", GetCurrentThreadId(), g_j, g_Buffer[g_j]); */ printf(" 編號為%d的消費者從緩衝池第%d個緩衝區取出資料%d\n",GetCurrentThreadId(), g_j, g_Buffer[g_j]); SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); if (g_Buffer[g_j] == END_PRODUCE_NUMBER)//結束標誌 { LeaveCriticalSection(&g_cs); //通知其它消費者有新資料了(結束標誌) //ReleaseSemaphore(g_hSemaphoreBufferFull, 1, NULL); break; } g_j = (g_j + 1) % BUFFER_SIZE; LeaveCriticalSection(&g_cs); Sleep(50); //some other work to do ReleaseSemaphore(g_hSemaphoreBufferEmpty, 1, NULL); } SetConsoleColor(FOREGROUND_GREEN); printf(" 編號為%d的消費者收到通知,線程結束運行\n", GetCurrentThreadId()); SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); return 0; } int main() { printf(" 生產者消費者問題 3生產者 1消費者 4緩衝區\n"); printf(" -- by MoreWindows( http://blog.csdn.net/MoreWindows ) --\n\n"); InitializeCriticalSection(&g_cs); //初始化訊號量,一個記錄有產品的緩衝區個數,另一個記錄空緩衝區個數. g_hSemaphoreBufferEmpty = CreateSemaphore(NULL, 4, 4, NULL); g_hSemaphoreBufferFull = CreateSemaphore(NULL, 0, 4, NULL); g_i = 0; g_j = 0; memset(g_Buffer, 0, sizeof(g_Buffer)); const int THREADNUM = 4; HANDLE hThread[THREADNUM]; //生產者線程 3個 hThread[0] = (HANDLE)_beginthreadex(NULL, 0, ProducerThreadFun, NULL, 0, NULL); hThread[1] = (HANDLE)_beginthreadex(NULL, 0, ProducerThreadFun, NULL, 0, NULL); hThread[2] = (HANDLE)_beginthreadex(NULL, 0, ProducerThreadFun, NULL, 0, NULL); //消費者線程 1個 hThread[3] = (HANDLE)_beginthreadex(NULL, 0, ConsumerThreadFun, NULL, 0, NULL); WaitForMultipleObjects(THREADNUM, hThread, TRUE, INFINITE); for (int i = 0; i < THREADNUM; i++) CloseHandle(hThread[i]); //銷毀訊號量和關鍵段 CloseHandle(g_hSemaphoreBufferEmpty); CloseHandle(g_hSemaphoreBufferFull); DeleteCriticalSection(&g_cs); return 0; }
運行結果如下:
reference:http://blog.csdn.net/morewindows/article/details/7577591