操作系统的经典问题
生产者和消费者问题的编程,使用语言为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;
}