#include <stdio.h>
#include <windows.h>
#define P(S) WaitForSingleObject(S,INFINITE)//定義Windows下的P操作
#define V(S) ReleaseSemaphore(S,1,NULL)//定義Windows下的V操作
//生產者 消費者 緩沖區
#define num_of_productors 2
#define num_of_consumers 3
#define num_of_buffers 3
int nextp = 1; //下一個產品的編號
int in = 0, out = 0; //分別指向下一個存放產品和取出產品的緩沖區編號
int g_Buffer[num_of_buffers] = { 0 }; //緩沖區初始值為空
HANDLE g_hSemaphoreEmpty, g_hSemaphoreFull, g_hMutex;
//生產者線程函數
DWORD WINAPI ProducerThreadFun(LPVOID pM)
{
Sleep(100);
do{
int id = *((int*)(pM)); //生產者編號
P(g_hSemaphoreEmpty);
P(g_hMutex);
g_Buffer[in] = nextp;
printf("生產者%d將數據%d放入緩沖區%d\n", id, nextp, in);
nextp++;
in = (in + 1) % num_of_buffers;
V(g_hMutex);
V(g_hSemaphoreFull);
Sleep(100);
if (nextp > 12) break;
} while(true);
return 0;
}
//消費者線程函數
DWORD WINAPI ConsumerThreadFun(LPVOID pM)
{
Sleep(100);
do
{
int id = *((int*)(pM)); //消費者編號
P(g_hSemaphoreFull);
P(g_hMutex);
//nextp = g_Buffer[out];
printf(" 消費者%d從緩沖區%d中取數據%d\n", id, out, g_Buffer[out]);
out = (out + 1) % num_of_buffers;
V(g_hMutex);
V(g_hSemaphoreEmpty);
Sleep(100);
} while (true);
}
int main()
{
int num[num_of_productors + num_of_consumers];
printf(" 生產者消費者問題:%d生產者 %d消費者 %d緩沖區\n", num_of_productors, num_of_consumers, num_of_buffers);
//初始值為num_of_buffers的信號量
g_hSemaphoreEmpty = CreateSemaphore(NULL, num_of_buffers, num_of_buffers, NULL); //繼承/初始化信號計數/最大信號計數/名稱
//初始值為0的信號量
g_hSemaphoreFull = CreateSemaphore(NULL, 0, num_of_buffers, NULL);
//互斥量
g_hMutex = CreateSemaphore(NULL, 1, 1, NULL);
const int THREADNUM = num_of_productors + num_of_consumers; //線程數
HANDLE hThread[THREADNUM];
for (int i = 0; i < num_of_productors; i++) //創建生產者線程
{
num[i] = i + 1;
hThread[i] = CreateThread(NULL, 0, ProducerThreadFun, (LPVOID *)&num[i], 0, NULL);
} //繼承/初始棧大小/線程函數/向線程函數傳遞的參數/線程標志 0 表示創建后立即激活/保存新線程的ID
for (int i = num_of_productors; i < num_of_productors + num_of_consumers; i++) //創建消費者者線程
{
num[i] = i - num_of_productors + 1;
hThread[i] = CreateThread(NULL, 0, ConsumerThreadFun, (LPVOID *)&num[i], 0, NULL);
}
WaitForMultipleObjects(THREADNUM, hThread, TRUE, INFINITE);
system("pause");
return 0;
}