下面是实现操作系统消费者—生产者的代码
为什么运行结果里面每个生产者产生的第一个数据值都是一样的,第二个数据也一样.......,明明是用rand()取的随机种子值????
还有为什么消费者子线程一直没有结束???
#pragma once
#include<iostream>
#include<windows.h>
#include<time.h>
using namespace std;
//缓冲区结构
typedef struct Buffer
{
DWORD data; //数据
int Number; //线程序号
}*lpBuffer;
//生产者线程的工作代码
DWORD WINAPI ProducerThread(LPVOID p);
//消费者线程的工作代码
DWORD WINAPI ConsumerThread(LPVOID p);
//描述生产者-消费者的类
class sy_pc
{
private:
int in; //生产者使用的循环缓冲区的下标
int out; //消费者使用的循环缓冲区的下标
int bcount; //循环缓冲区的个数
HANDLE empty; //指向生产者的私有信号量
HANDLE full; //指向消费者的私有信号量
HANDLE mutex; //指示互斥信号量
lpBuffer buffer; //指向一个循环缓冲区
public:
sy_pc(int); //构造函数
int getbuffer(lpBuffer); //从缓冲区取出一个“产品”
int putbuffer(Buffer); //向缓冲区放入一个“产品”
~sy_pc(); //析构函数
};
sy_pc::sy_pc(int c)
{
in = 0;
out = 0;
bcount = c;
empty = CreateSemaphore(NULL, bcount, bcount, "sempty");
full= CreateSemaphore(NULL, 0, bcount, "sfull");
mutex= CreateSemaphore(NULL, 1, 1, "smutex");
buffer = new Buffer[bcount];
}
int sy_pc::getbuffer(lpBuffer Buf)
{
WaitForSingleObject(full, INFINITE);
WaitForSingleObject(mutex, INFINITE);
*Buf = buffer[out];
out = (out + 1) % bcount;
ReleaseSemaphore(mutex, 1, NULL);
ReleaseSemaphore(empty, 1, NULL);
return out;
}
int sy_pc::putbuffer(Buffer b)
{
WaitForSingleObject(empty, INFINITE);
WaitForSingleObject(mutex, INFINITE);
buffer[in]=b;
in = (in + 1) % bcount;
ReleaseSemaphore(mutex, 1, NULL);
ReleaseSemaphore(full, 1, NULL);
return in;
}
sy_pc::~sy_pc()
{
delete[]buffer;
}
#include "P_C.h"
#define M 5 //假设有5个生产者
#define N 3 //假设有3个消费者
CRITICAL_SECTION cs_Screen; //因多线程竞争屏幕,故设次临界区控制变量
sy_pc s_pc(10); //定义全局变量,简化参数传递方式
void main()
{
HANDLE hThread[100]; //假设最多创建100个线程
int i, j, sum;
DWORD ExitCode;
InitializeCriticalSection(&cs_Screen); //初始化临界区对象cs_Screen
srand((unsigned int)time(NULL)); //使用当前时间为随机序列的“种子”
for (i = 1, j = 0; i < M; i++, j++) //创建5个生产者线程
{ //每个生产者线程执行ProducerThread()的代码
hThread[j] = CreateThread(NULL, 0, ProducerThread, (LPVOID)&i, 0, NULL);
Sleep(10);
}
for (i = 1; i <= N; i++, j++) //创建3个消费者线程
{ //每个生产者线程执行ConsumerThread()的代码
hThread[j] = CreateThread(NULL, 0, ConsumerThread, (LPVOID)&i, 0, NULL);
Sleep(10);
}
while (true) //主线程不断循环,直到所有子线程结束
{
EnterCriticalSection(&cs_Screen);//准备进入临界区
cout << "主线程正在运行*******************" << endl;
LeaveCriticalSection(&cs_Screen);//退出临界区
Sleep(1000);
for (i = 0, sum = 0; i < j; i++)//总共j个子线程
{
ExitCode = 0;
GetExitCodeThread(hThread[i], &ExitCode);//获得子线程的退出码
if (ExitCode == 1) //如果该线程也结束,则统计入sum
sum = sum + ExitCode;
}
if (sum == j) //若所有子线程已经结束,则主线程也结束
break;
}
cout << "所有子线程已经结束,主线程也将结束****************" << endl;
}
//生产者线程的工作代码
DWORD WINAPI ProducerThread(LPVOID p)
{
int *ip = (int*)p;
int ThreadNumber = *ip;
int naptime, in;
Buffer b;
for (int i = 1; i <= 3*N; i++) //每个生产者共生产9个产品放入缓冲区
{
b.data = rand();
b.Number = ThreadNumber;
in = s_pc.putbuffer(b);
EnterCriticalSection(&cs_Screen);
cout << "Producer" << ThreadNumber << "向缓冲区投放了第 "
<< i << " 个数据" << b.data << "。 in=" << in << endl;
LeaveCriticalSection(&cs_Screen);
naptime = 100 + rand() % 200;
Sleep(naptime);
}
EnterCriticalSection(&cs_Screen);
cout << "Producer" << ThreadNumber << " 运行完毕" << endl;
LeaveCriticalSection(&cs_Screen);
return 1;
}
//消费者线程的工作代码
DWORD WINAPI ConsumerThread(LPVOID p)
{
int ThreadNumber = *((int*)p);
int naptime, out;
Buffer b;
for (int i = 1; i <= 3*M; i++) //每个消费者共获取15个产品后结束
{
out = s_pc.getbuffer(&b);
EnterCriticalSection(&cs_Screen);
cout << "Consumer" << ThreadNumber << "从缓冲区取得了第 "
<< i << " 个数据" << b.data;
cout<<",它是Producer" <<b.Number << "存放的。out=" << out << endl;
LeaveCriticalSection(&cs_Screen);
naptime = 100 + rand() % 200;
Sleep(naptime);
}
EnterCriticalSection(&cs_Screen);
cout << "Consumer" << ThreadNumber << " 运行完毕" << endl;
LeaveCriticalSection(&cs_Screen);
return 1;
}
``