首页 > 解决方案 > 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;
}

标签: c++concurrency

解决方案


为什么消费者线程阻塞?

我已经测试了您的代码,结果证明是生产者线程阻塞了该put()方法。为什么?

想象以下场景:向量中有 13 个项目items

主线程(生产者)愉快地加载前 12 个项目,并等待cv低于currentSize12。

消费者线程被通知,并愉快地消费前12个项目,然后等待cv变为currentSize大于0。

可是等等!现在每个人都在等着什么,没有人通知。因此,所有线程都会阻塞。currentSize低于 12时需要通知生产者。


推荐阅读