BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #89728同步于 2015/12/18
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖

windows下生产消费模型怎么实现?

jufds7788
2015/12/18镜像同步13 回复
本来想发到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; }
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
jufds7788机器人#1 · 2015/12/19
原来使用WaitForMultipleObjects来等待事件数组就可以将事件和缓冲区对应起来了。。[ema27]
mnhg123机器人#2 · 2015/12/19
LZ 有本叫《windows核心编程》的书 发自「贵邮」
nuanyangyang机器人#3 · 2015/12/19
如果是Windows爱好者的话,请用C#。多线程是非常麻烦的东西。需要一个高级的编程语言。
tastier机器人#4 · 2015/12/19
缓冲区中的数据不是被顺序取走的吗,空闲也是顺序的?
icybee机器人#5 · 2015/12/19
rabbitmq
jufds7788机器人#6 · 2015/12/19
嗯 正打算看 【 在 mnhg123 (民曰我自然) 的大作中提到: 】 : LZ 有本叫《windows核心编程》的书
jufds7788机器人#7 · 2015/12/19
仅仅是为了理解Windows api的用法而已。。对c#程序逆向的结果和对c/c++逆向的结果貌似不一样 【 在 nuanyangyang (暖羊羊) 的大作中提到: 】 : 如果是Windows爱好者的话,请用C#。多线程是非常麻烦的东西。需要一个高级的编程语言。
jufds7788机器人#8 · 2015/12/19
是顺序被取走的。。所以不对啊,应该是先顺序放,然后哪有空的放哪里吧。。我不能很好地描述出来- - 【 在 tastier (老司机带带我) 的大作中提到: 】 : 缓冲区中的数据不是被顺序取走的吗,空闲也是顺序的?
nuanyangyang机器人#9 · 2015/12/19
【 在 jufds7788 的大作中提到: 】 : 仅仅是为了理解Windows api的用法而已。。对c#程序逆向的结果和对c/c++逆向的结果貌似不一样 那,加油吧。多线程是高级话题,很难的。另外,要不要关注一下C++11的新的多线程API? 还有“C++ memory model”,很有意思的话题。