Windows下Semaphore 经典生产者消费者

// product_consumer.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>


#define P(S) WaitForSingleObject (S, INFINITE)            //定义P操作
#define V(S) ReleaseSemaphore (S, 1, NULL)                //定义V操作

#define MUTEX_LOCK(m) WaitForSingleObject(m, INFINITE)
#define MUTEX_UNLOCK(m) ReleaseMutex(m)



#define CONSUMER_NUM 10            /* 消费者个数 */
#define PRODUCER_NUM 10            /* 生产者个数 */
#define BUFFER_NUM   5             /* 缓冲区个数 */

const char *c_string_fruit[10] = { "桔子", "苹果", "香蕉", "菠萝", "草莓", "荔枝", "樱桃", "葡萄", "桃子", "鸭梨" };

const char *g_item_buffer[BUFFER_NUM] = { 0 };
int g_item_product_index = 0;
int g_item_consume_index = 0;

HANDLE g_sem_product = NULL;
HANDLE g_sem_consume = NULL;
HANDLE g_sec_mutex = NULL;


//生产者线程
DWORD WINAPI thread_product(LPVOID para)
{
	int i = (int)para;
	printf("生产者[%02d]: 我来啦 ...\n", i);

	srand(GetTickCount() + GetCurrentThreadId());

	while (true)
	{
		printf("生产者[%02d]: 生产中 ...\n", i);
		Sleep(1000 * rand() % 10 + 110);
		
		const char *fruit = c_string_fruit[rand() % _countof(c_string_fruit)];
		printf("生产者[%02d]: 生产一个水果: %s\n", i, fruit);
		
		P(g_sem_product);
		
		MUTEX_LOCK(g_sec_mutex);
		g_item_buffer[g_item_product_index] = fruit;
		g_item_product_index = (g_item_product_index + 1) % BUFFER_NUM;
		MUTEX_UNLOCK(g_sec_mutex);

		Sleep(1000 / 2 * rand() % 10 + 110);

		printf("生产者[%02d]: 放置一个水果: %s\n", i, fruit);

		V(g_sem_consume);
	}

	return 0;
}


//消费者线程
DWORD WINAPI thread_consume(LPVOID para)
{
	int i = (int)para;
	printf("消费者[%02d]: 我来啦 ...\n", i);

	srand(GetTickCount() + GetCurrentThreadId());

	while (1)
	{
		printf("消费者[%02d]: 我要吃 ...\n", i);

		const char *fruit = NULL;

		P(g_sem_consume);

		MUTEX_LOCK(g_sec_mutex);
		fruit = g_item_buffer[g_item_consume_index];
		g_item_buffer[g_item_consume_index] = NULL;
		g_item_consume_index = (g_item_consume_index + 1) % BUFFER_NUM;
		MUTEX_UNLOCK(g_sec_mutex);

		printf("消费者[%02d]: 开始吃 %s\n", i, fruit);
		Sleep(1000 * rand() % 10 + 110);
		printf("消费者[%02d]: 吃完毕 %s\n", i, fruit);
		
		V(g_sem_product);
	}
	return 0;
}

int main()
{
	setlocale(LC_ALL, "chs");

	//初始化信号量
	g_sec_mutex = CreateMutex(NULL, FALSE, NULL);
	g_sem_product = CreateSemaphore(NULL, BUFFER_NUM, BUFFER_NUM, _T("SEM_PRODUCT"));
	g_sem_consume = CreateSemaphore(NULL, 0, BUFFER_NUM, _T("SEM_CONSUME"));
	if (g_sem_product == NULL 
		|| g_sem_consume == NULL 
		|| g_sec_mutex == NULL)
	{
		printf("创建信号量或互斥体失败!\n");
		return -1;
	}

	//线程计数, 前面为消费者线程, 后面为生产者线程
	HANDLE hThreadConsume[CONSUMER_NUM] = { 0 };
	HANDLE hThreadProduct[PRODUCER_NUM] = { 0 };

	for (int i = 0; i < CONSUMER_NUM; i++)
	{
		DWORD dwThreadId = 0;
		hThreadConsume[i] = CreateThread(NULL, 0, thread_consume, (LPVOID)i, 0, &dwThreadId);
		if (hThreadConsume[i] == NULL)
		{
			printf("创建消费者线程失败!\n");
			return -1;
		}
	}

	for (int i = 0; i < PRODUCER_NUM; i++)
	{
		DWORD dwThreadId = 0;
		hThreadProduct[i] = CreateThread(NULL, 0, thread_product, (LPVOID)i, 0, &dwThreadId);
		if (hThreadConsume[i] == NULL)
		{
			printf("创建生产者者线程失败!\n");
			return -1;
		}
	}

	//生产者和消费者的执行
	WaitForMultipleObjects(CONSUMER_NUM, hThreadConsume, TRUE, INFINITE);
	WaitForMultipleObjects(PRODUCER_NUM, hThreadProduct, TRUE, INFINITE);

	return 0;
}

如果有问题欢迎评论指正

posted @ 2021-09-27 16:35  XIE晓乐  阅读(185)  评论(0编辑  收藏  举报