返回信息流本来想发到windows版的。。但是那里实在没有讨论这个的- -只好发到这里了
参考:http://blog.csdn.net/morewindows/article/details/7577591
问题描述:
有一个生产者在生产产品,这 些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个具有多个缓冲区的缓冲池,生产者将它生产的产品放入一个缓冲区 中,消费者可以从缓冲区中取走产品进行消费,显然生产者和消费者之间必须保持同步,即不允许消费者到一个空的缓冲区中取产品,也不允许生产者向一个已经放 入产品的缓冲区中再次投放产品。
1个生产者、4个缓冲区、3个消费者。原代码中虽然做到了同步,但是感觉并没有完全实现这个模型的功能,因为不能做到哪个缓冲区空了就填充哪个。。现在问题是不知道怎么知道具体是哪一个缓冲区空闲。。怎么才能做到呢?
以下是原代码:
#include <iostream>
#include <Windows.h>
#include <process.h>
const int BUFFER_COUNTS = 4; //缓冲区个数
const int END_PRODUCE_NUMBER = 24; //生产产品个数
const unsigned int CONSUMER_COUNTS = 3; //消费者个数
int Production[BUFFER_COUNTS]; //缓冲池
CRITICAL_SECTION buffer_cs; //缓冲区的临界区
HANDLE hBuffer_empty, hBuffer_full; //通知缓冲区清空\填满的信号量
int g_i, g_j;
HANDLE hConsumer; //消费者同步事件
volatile bool flag = true;
//设置控制台字体颜色
BOOL SetConsoleColor(WORD wAttributes)
{
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
if (hConsole == INVALID_HANDLE_VALUE)
return FALSE;
return SetConsoleTextAttribute(hConsole, wAttributes);
}
//消费者线程
void __cdecl Consumer(void *Param)
{
int Index = *(int*)Param;
SetEvent(hConsumer);
while (true)
{
WaitForSingleObject(hBuffer_full, INFINITE); //等待非空缓冲区出现
if (Production[g_j] == 0)
{
goto CALL;
}
EnterCriticalSection(&buffer_cs); //进入临界区
SetConsoleColor(FOREGROUND_GREEN);
std::cout << "消费者" << Index << "从" << g_j << "号缓冲区取出了产品" << Production[g_j] << std::endl;
SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
if (Production[g_j] == END_PRODUCE_NUMBER)//结束标志
{
Production[g_j] = 0;
LeaveCriticalSection(&buffer_cs);
//通知其它消费者结束标志
CALL:
ReleaseSemaphore(hBuffer_full, 1, NULL);
break;
}
g_j = (g_j + 1) % BUFFER_COUNTS;
LeaveCriticalSection(&buffer_cs); //离开临界区
Sleep(50);
ReleaseSemaphore(hBuffer_empty, 1, NULL); //通知有空的缓冲区出现
}
SetConsoleColor(FOREGROUND_GREEN);
printf("编号为%d的消费者收到通知,线程结束运行\n", Index);
SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
_endthread(); //会隐式地CloseHanlde
}
//生产者线程
void __cdecl Productor(void *Param)
{
for (int i = 0; i < END_PRODUCE_NUMBER; i++)
{
WaitForSingleObject(hBuffer_empty, INFINITE); //等待有空的缓冲区出现
//互斥的访问缓冲区
EnterCriticalSection(&buffer_cs); //进入临界区
Production[g_i] = i + 1;
std::cout << "生产者在" << g_i << "号缓冲区中放置了一个产品" << Production[g_i] << std::endl;
g_i = (g_i + 1) % BUFFER_COUNTS;
LeaveCriticalSection(&buffer_cs); //离开临界区
//通知缓冲区被填充
ReleaseSemaphore(hBuffer_full, 1, NULL);
}
std::cout << "**********************************\n所有产品投放完毕,结束生产者线程\n**********************************" << std::endl;
_endthread(); //会隐式地CloseHanlde
}
int main(int argc, char *argv[])
{
hBuffer_full = CreateSemaphore(NULL, 0, BUFFER_COUNTS, NULL);
hBuffer_empty = CreateSemaphore(NULL, BUFFER_COUNTS, BUFFER_COUNTS, NULL);
g_i = 0;
g_j = 0;
memset(Production, 0, sizeof(Production));
InitializeCriticalSection(&buffer_cs); //初始化临界区
hConsumer = CreateEvent(NULL, FALSE, FALSE, NULL); //自动置位
SetEvent(hConsumer);
HANDLE hThread[CONSUMER_COUNTS];
int thread_index = 0;
HANDLE hThread_Productor = (HANDLE)_beginthread(Productor, NULL, NULL);
for (int i = 0; i < CONSUMER_COUNTS; i++)
{
WaitForSingleObject(hConsumer, INFINITE);
thread_index = i + 1;
hThread[i] = (HANDLE)_beginthread(Consumer, NULL, &thread_index);
}
WaitForSingleObject(hThread_Productor, INFINITE);
for (int i = 0; i < CONSUMER_COUNTS; i++)
{
WaitForSingleObject(hThread[i], INFINITE);
}
CloseHandle(hBuffer_full);
CloseHandle(hBuffer_empty);
DeleteCriticalSection(&buffer_cs);
return 0;
}
这是一条镜像帖。来源:北邮人论坛 / cpp / #89728同步于 2015/12/18
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
windows下生产消费模型怎么实现?
jufds7788
2015/12/18镜像同步13 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
仅仅是为了理解Windows api的用法而已。。对c#程序逆向的结果和对c/c++逆向的结果貌似不一样
【 在 nuanyangyang (暖羊羊) 的大作中提到: 】
: 如果是Windows爱好者的话,请用C#。多线程是非常麻烦的东西。需要一个高级的编程语言。
是顺序被取走的。。所以不对啊,应该是先顺序放,然后哪有空的放哪里吧。。我不能很好地描述出来- -
【 在 tastier (老司机带带我) 的大作中提到: 】
: 缓冲区中的数据不是被顺序取走的吗,空闲也是顺序的?
【 在 jufds7788 的大作中提到: 】
: 仅仅是为了理解Windows api的用法而已。。对c#程序逆向的结果和对c/c++逆向的结果貌似不一样
那,加油吧。多线程是高级话题,很难的。另外,要不要关注一下C++11的新的多线程API?
还有“C++ memory model”,很有意思的话题。