生产者消费者

操作系统的经典问题
生产者和消费者问题的编程,使用语言为C++,这是操作系统实验课上的编程,拿出来和大家分享,不足之处还望指出,谢谢。

// 生产者消费者
#include<iostream>
#include<queue>
#include<Windows.h>
using namespace std;

struct Product//生产的产品
{
	int id;//产品的id
	int bufferPos;//产品所在的缓冲池的位置
};

queue<Product> g_queue;//缓冲池队列
HANDLE bufferFullSemaphore;//缓冲池满的信号量
HANDLE bufferEmptySemaphore;//缓冲池空的信号量
HANDLE mutex;//操作互斥锁
static int num = 0;//当前池子的位置
DWORD WINAPI producerFunc(LPVOID n);//生产者进程函数
DWORD WINAPI consumerFunc(LPVOID n);//消费者进程函数
int bufferSize;//缓冲池大小
int CostTask = 0;//消费多少个就结束
int CostNum = 0;//当前消费的数量
DWORD thrdId;


class Producer {//生产者的类
public:
	Producer() {
		handle = CreateThread(NULL, 0, producerFunc, this, 0, &thrdId);//创建一个线程
		ID = GetThreadId(this->handle);//将线程的ID设置为此生产者的ID
		productNum = 0;//已经生产的产品的数量
		product.id = ID;//将此生产者生产的产品ID设置为生产者ID

	}
	int getID() {
		return ID;
	}
	int getProductNum() {
		return productNum;
	}
	void IncProductNum() {
		productNum++;
	}
	HANDLE getHandle() {
		return handle;
	}
	Product getProduct() {
		return product;
	}
	void setProductPos(int n) {
		product.bufferPos = n;
	}

protected:
	HANDLE handle;
	int productNum;
	int ID;
	Product product;
};

class Consumer {//消费者类,基本同上
public:
	Consumer() {
		handle = CreateThread(NULL, 0, consumerFunc, this, 0, &thrdId);//其中this传递对象的指针
		ID = GetThreadId(this->handle);
		consumeNum = 0;
	}
	int getID() {
		return ID;
	}
	int getConsumeNum() {
		return consumeNum;
	}
	void IncConsumeNum() {
		consumeNum++;
	}
	HANDLE getHandle() {
		return handle;
	}
protected:
	HANDLE handle;
	int consumeNum;
	int ID;
};

DWORD WINAPI producerFunc(LPVOID n)
{
	Producer * thisInfo = reinterpret_cast<Producer*>(n);//将无类型的指针强制转化为我们需要类型的指针
	while (true)
	{
		WaitForSingleObject(bufferEmptySemaphore, INFINITE);//等待buffer为空的信号量,意思是当buffer不满的时候,可以进行
		WaitForSingleObject(mutex, INFINITE);//等待操作的信号量
		if (CostNum<CostTask)//当当前的消费数量小于我们的目标数量时,进行操作
		{
			thisInfo->setProductPos(num);
			g_queue.push(thisInfo->getProduct());//将产品放入缓冲池
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN);
			cout << "编号为:" << thisInfo->getID() << "生产了一件产品,放入" << num % bufferSize << "号缓冲池" << endl;
			thisInfo->IncProductNum();//此生产者生产数量+1
			num++;//缓冲池移向下一个位置
			ReleaseMutex(mutex);//释放操作锁
			ReleaseSemaphore(bufferFullSemaphore, 1, NULL);//指定信号量+1
			Sleep(500);
		}
		else
		{
			ReleaseMutex(mutex);//释放操作锁
			ReleaseSemaphore(bufferFullSemaphore, 1, NULL);//指定信号量+1
			Sleep(500);
			break;
		}
		
	}
	return 0;
}
DWORD WINAPI consumerFunc(LPVOID n)
{
	Consumer* thisInfo = reinterpret_cast<Consumer*>(n);
	while (true)
	{

		WaitForSingleObject(bufferFullSemaphore, INFINITE);
		WaitForSingleObject(mutex, INFINITE);
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
		if (CostNum < CostTask)
		{
			thisInfo->IncConsumeNum();
			cout << "编号为:" << thisInfo->getID() << "消费了编号为:" << g_queue.front().id << "生产的一件产品,在" << g_queue.front().bufferPos % bufferSize << "号缓冲池" << endl;
			CostNum++;
			g_queue.pop();
			ReleaseMutex(mutex);
			ReleaseSemaphore(bufferEmptySemaphore, 1, NULL);//指定信号量+1
			Sleep(500);
		}
		else
		{
			ReleaseMutex(mutex);//释放操作锁
			ReleaseSemaphore(bufferFullSemaphore, 1, NULL);//指定信号量+1
			Sleep(500);
			break;
		}
	}
	return 0;
}


int main()
{
	int P, C;
	HANDLE handle[2];
	Producer* producers;
	Consumer* consumers;
	HANDLE* handles;
	
	mutex = CreateMutex(NULL, false, NULL);//false代表开始的时候不属于任何进程
	cout << "消费者生产者问题----Way" << endl;
	cout << "-----------------------------------"<< endl;
	cout << "请输入生产者数量:";
	cin >> P;
	cout << "请输入消费者数量:";
	cin >> C;
	cout << "请输入缓冲池大小:";
	cin >> bufferSize;
	cout << "请输入最大消费数量:";
	cin >> CostTask;
	bufferFullSemaphore = CreateSemaphore(NULL, 0, bufferSize, NULL);//初始资源设定为
	bufferEmptySemaphore = CreateSemaphore(NULL, bufferSize, bufferSize, NULL); //初始资源为


	producers = new Producer[P];
	consumers = new Consumer[C];
	WaitForSingleObject(producers[0].getHandle(), INFINITE);//等待第一个生产者返回,加这个语句的目的是,为了等所有的生产者和消费者完成任务以后,再执行往后的语句,不然由于并行的原因,最后打印结果会不正确
	
	for ( int i = 0; i < P; i++)
	{
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);
		cout << "编号为:" << producers[i].getID() << "生产了:" << producers[i].getProductNum() << "件商品"<<endl;
		
	}
	for (int i = 0; i < C ; i++)
	{
		cout << "编号为:" << consumers[i].getID() << "消费了:" << consumers[i].getConsumeNum() << "件商品"<<endl;

	}

	for (int i = 0; i < P; i++)
	{
		CloseHandle(producers[i].getHandle());
	}

	for (int i = 0; i < C; i++)
	{
		CloseHandle(consumers[i].getHandle());
	}

	delete producers, consumers;

	CloseHandle(bufferEmptySemaphore);
	CloseHandle(bufferFullSemaphore);
	CloseHandle(mutex);
	getchar();
	getchar();
	return 0;
	}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值