c++ - C ++多个消费者线程卡在条件变量上
问题描述
我正在用 C++ 制作一个生产者、多个消费者的程序。我首先调用消费者线程,然后将元素添加到数组中。一切正常,但最终消费者线程没有加入,因为它们被卡在等待条件变量并且程序冻结。
我认为问题在于线程在循环中不断被调用,因为 currentSize 不受保护,它们无法退出条件变量,但我不知道如何解决它。
struct Item {
public:
string name;
int time;
double height;
};
struct Monitor {
private:
Item items[12];
int currentSize;
bool finished;
mutex lock;
condition_variable cv;
public:
Monitor() {
finished = false;
currentSize = 0;
}
void put(Item item) {
unique_lock<mutex> guard(lock);
cv.wait(guard, [&] { return (currentSize < 12); });
items[currentSize] = item;
currentSize++;
cv.notify_all();
}
Item get() {
unique_lock<mutex> guard(lock);
cv.wait(guard, [&] { return (currentSize > 0); });
Item item = items[currentSize - 1];
currentSize--;
return item;
}
bool get_finished() {
return finished;
}
void set_finished() {
finished = true;
}
int get_size() {
return currentSize;
}
};
int main() {
vector<Item> items = read_file(file);
Monitor monitor;
vector<thread> threads;
vector<Item> results;
for (int i = 0; i < 4; i++) {
threads.emplace_back([&] {
while (!monitor.get_finished()) {
if (monitor.get_size() > 0) {
Item item = monitor.get();
results.push_back(item);
}
}
});
}
for (int i = 0; i < items.size(); i++) {
monitor.put(items[i]);
}
monitor.set_finished();
for_each(threads.begin(), threads.end(), mem_fn(&thread::join));
return 0;
}
解决方案
为什么消费者线程阻塞?
我已经测试了您的代码,结果证明是生产者线程阻塞了该put()
方法。为什么?
想象以下场景:向量中有 13 个项目items
。
主线程(生产者)愉快地加载前 12 个项目,并等待cv
低于currentSize
12。
消费者线程被通知,并愉快地消费前12个项目,然后等待cv
变为currentSize
大于0。
可是等等!现在每个人都在等着什么,没有人通知。因此,所有线程都会阻塞。currentSize
低于 12时需要通知生产者。
推荐阅读
- javascript - MuseJSAssert:调用选择器函数时出错:TypeError:this.elem.get(...) 未定义
- linux - zsh 打印转义字符以记录
- unity3d - *已解决*我无法让我的精灵在 Unity 中触发对撞机
- acumatica - 将自定义字段中的值复制到 RowPersisting 事件中的 TaxRegistrationID 字段
- laravel - 使用标头参数的邮递员授权工作但不适用于 Axios 标头
- apache - 我正在尝试使用 ssl xampp 创建自签名证书,但出现以下错误
- ms-access - 带有查询参数的函数中的 OpenRecordSet
- c# - 使用 Jquery 在 Linq to sql 中删除不起作用?
- google-apps-script - 如何让 Google 表单发送带有新回复的自动电子邮件
- java - 如何使用 kotlin 中的导航组件以编程方式返回上一个片段?