我试图弄清楚如何在std::condition_variable中使用C++实现一个“奇怪”的生产者和消费者程序,在这个程序中,我对count变量设置了一个限制。
主线程(“生产者”)增加计数,必须等待此值返回为零才能发出新的增量。
其他线程进入一个循环,它们必须减少计数器并发出通知。
我被阻塞了,因为我不清楚如何通过在所有线程的函数中有序地退出while循环来结束程序。
有人能给我一些关于如何实施它的指导吗?
代码
#include <iostream>
#include <thread>
#include <condition_variable>
#include <vector>
int main() {
int n_core = std::thread::hardware_concurrency();
std::vector<std::thread> workers;
int max = 100;
int count = 0;
std::condition_variable cv;
std::mutex mutex;
int timecalled = 0;
for (int i = 0; i < n_core; i++) {
workers.emplace_back(std::thread{[&max, &count, &mutex, &cv]() {
while (true) {
std::unique_lock<std::mutex> lk{mutex};
std::cout << std::this_thread::get_id() << " cv" << std::endl;
cv.wait(lk, [&count]() { return count == 1; });
std::cout << std::this_thread::get_id() << " - " << count << std::endl;
count--;
std::cout << std::this_thread::get_id() << " notify dec" << std::endl;
cv.notify_all();
}
}});
}
while (max > 0) {
std::unique_lock<std::mutex> lk{mutex};
std::cout << std::this_thread::get_id() << " cv" << std::endl;
cv.wait(lk, [&count]() { return count == 0; });
std::cout << std::this_thread::get_id() << " created token" << std::endl;
count++;
max--;
timecalled++;
std::cout << std::this_thread::get_id() << " notify inc" << std::endl;
cv.notify_all();
}
for (auto &w : workers) {
w.join();
}
std::cout << timecalled << std::endl; // must be equal to max
std::cout << count << std::endl; // must be zero
}问题
程序不会结束,因为它被某些最终的join卡住了。
预期结果
预期结果必须是:
100
0编辑
编辑1:我用true替换了true中的max > 0。现在循环是无界的,但是使用@prog的解决方案似乎是可行的。
编辑2:我最后添加了一个变量来检查结果。
编辑3:我将while(true)更改为while(max >0)。这会不会是并发中的一个问题,因为我们是在没有锁的情况下阅读它呢?
发布于 2019-07-17 12:01:43
max可以由多个线程读取,而在main中正在修改它,这是一种根据C++标准的竞争条件。wait中使用的谓词似乎不正确(您使用的是==)。https://stackoverflow.com/questions/57074998
复制相似问题