運行結果
流程圖
廢話不多說,直接上代碼
1 #include<iostream> 2 #include <string> 3 #include <unistd.h> //sleep函數庫文件 4 #include<process.h> 5 #include<windows.h>//句多線程柄庫文件 6 #define n 10 //緩沖區大小 7 #define sleepTime 2 //控制生產者消費者的生產和消費速度,便於演示觀察 8 #define executime 3000//模擬生產消費者算法的時間長 9 using namespace std; 10 11 typedef HANDLE semaphore; //互斥信號量句柄 12 typedef int item; //緩沖池中產品類型 13 14 item buffer[n] = {0}; //定義緩沖池,並全部置空 15 int in = 0; 16 int out = 0; 17 int counter = 0;//每當生產者進程向緩沖池中投放(或取走)一個產品后,使counter加1(或減1)。 18 semaphore mutex , empty , full ;//定義互斥信號量句柄 19 20 //模擬算法中涉及的課外知識 21 22 //HANDLE WINAPI CreateSemaphore( _In_opt_LPSECURITY_ATTRIBUTES lpSemaphoreAttributes ,_In_LONG lInitialCount, _In_ LONG lMaximumCount,_In_opt_? LPCTSTR lpName 23 //); 24 //第一個參數:安全屬性,如果為NULL則是默認安全屬性 25 //第二個參數:信號量的初始值,要>=0且<=第三個參數 26 //第三個參數:信號量的最大值 27 //第四個參數:信號量的名稱 28 // 29 //返回值:指向信號量的句柄,如果創建的信號量和已有的信號量重名,那么返回已經存在的信號量句柄 30 // 31 //DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds); 32 // 33 //第一個參數:等待對象的 handle(代表一個核心對象)。 34 //第二個參數:等待的最長時間。時間終了,即使 handle尚未成為激發狀態,此函數也要返回。此值可以是0(代表立刻返回),也可以是 INFINITE代表無窮等待。 35 // 36 //BOOL WINAPI ReleaseSemaphore( _In_ HANDLE hSemaphore,_In_ LONG lReleaseCount,_Out_opt_ LPLONG lpPreviousCount); 37 //第一個參數:信號量句柄 38 //第二個參數:釋放后,信號量增加的數目 39 //第三個參數:信號量增加前的值存放的地址,如果不需要則為NULL 40 //返回值:釋放是否成功 41 //void wait(semaphore &S) 42 //{ 43 // while (S<=0); 44 // S=S-1; 45 //} 46 // 47 //void signal(semaphore &S) 48 //{ 49 // S=S+1; 50 //} 51 // 52 53 void display(string str) 54 { 55 cout<<str<<endl; 56 cout<<"緩沖池:"; 57 for(int i=0;i<n;i++){ 58 cout<<buffer[i]<<' '; 59 // sleep(1); 減慢輸出速度 60 } 61 cout<<endl; 62 cout<<"counter:"<<counter<<endl<<endl; 63 //cout<<" mutex:"<<mutex<<" empty:"<<empty<<" full:"<<full<<endl<<endl; 由於是互斥信號量句柄,無法直接訪問其值 64 } 65 66 unsigned __stdcall producer(void*) 67 { 68 do{ 69 WaitForSingleObject(empty, INFINITE);//等待同步信號量empty 70 WaitForSingleObject(mutex, INFINITE);//等待互斥信號量mutex 71 item nextp=1; 72 buffer[in]=nextp; 73 in=(in+1)%n; 74 counter++; 75 display("生產一件產品"); 76 77 sleep(sleepTime); 78 ReleaseSemaphore(mutex, 1, NULL);//釋放互斥信號量mutex 79 ReleaseSemaphore(full, 1, NULL);//釋放同步信號量full 80 81 }while(1); 82 return 1; 83 } 84 85 unsigned __stdcall consumer(void* ) 86 { 87 do{ 88 WaitForSingleObject(full, INFINITE);//等待同步信號量full 89 WaitForSingleObject(mutex, INFINITE);//等待互斥信號量mutex 90 item nextc=buffer[out]; 91 buffer[out]=0; 92 out=(out+1)%n; 93 counter--; 94 sleep(sleepTime); 95 display("消費一件產品"); 96 ReleaseSemaphore(mutex, 1, NULL);//釋放互斥信號量mutex 97 ReleaseSemaphore(empty, 1, NULL);//釋放信號量 98 }while(1); 99 return 2; 100 } 101 102 int main(){ 103 int buf_max=n;//輸入緩沖區大小,整形變量,大於0,建議在10—20之間一個整數 ,這里為定義的宏n 104 int producerNum; //輸入生產者數量,整形變量,建議在4-8,直接,否則太大電腦跑不動,太小生產速度不夠 105 int consumerNum;//輸入消費者數量,整形變量,建議小於生產者數量,不要為 0 106 cout<<"請輸入生產者數量:";cin>>producerNum; 107 cout<<"請輸入消費者數量:";cin>>consumerNum; 108 empty = CreateSemaphore(NULL, buf_max, buf_max, NULL); //初值為緩沖池大小,最大為緩沖池大小 109 full = CreateSemaphore(NULL, 0, buf_max, NULL); //初值為0,最大為緩沖池大小 110 mutex = CreateSemaphore(NULL,1,1,NULL); //初值為1,最大為1 111 HANDLE hthproducer[producerNum], htconsumer[consumerNum];//定義生產者 消費者線程句柄池大小 112 113 //創建線程 114 int i; 115 116 for(i=0;i<producerNum;i++) 117 { 118 hthproducer[i] = (HANDLE)_beginthreadex(NULL, 0, producer, NULL, 0, NULL);//生產者線程 119 } 120 121 for(i=0;i<consumerNum;i++) 122 { 123 htconsumer[i] = (HANDLE)_beginthreadex(NULL, 0, consumer, NULL, 0, NULL);//消費者線程 124 } 125 126 127 128 //等待子線程結束 129 for(i=0;i<producerNum;i++) 130 WaitForSingleObject(hthproducer[i], executime);//在時間executime到達后無論是否激活線程,都會關閉線程 131 for(i=0;i<consumerNum;i++) 132 WaitForSingleObject(htconsumer[i], executime);//在時間executime到達后無論是否激活線程,都會關閉線程 133 134 //關閉句柄 135 for(i=0;i<producerNum;i++) 136 CloseHandle(hthproducer[i]); 137 for(i=0;i<consumerNum;i++) 138 CloseHandle(htconsumer[i]); 139 140 CloseHandle(empty); 141 CloseHandle(full); 142 CloseHandle(mutex); 143 144 cout<<"演示完畢,謝謝觀看"; 145 146 147 return 0; 148 }