【发布时间】:2017-01-06 12:11:33
【问题描述】:
#include <iostream>
#include <thread>
#include <condition_variable>
#include <queue>
#include <cstdlib>
#include <chrono>
#include <ctime>
#include <random>
using namespace std;
//counts every number that is added to the queue
static long long producer_count = 0;
//counts every number that is taken out of the queue
static long long consumer_count = 0;
void generateNumbers(queue<int> & numbers, condition_variable & cv, mutex & m, bool & workdone){
while(!workdone) {
unique_lock<std::mutex> lk(m);
int rndNum = rand() % 100;
numbers.push(rndNum);
producer_count++;
cv.notify_one();
}
}
void work(queue<int> & numbers, condition_variable & cv, mutex & m, bool & workdone) {
while(!workdone) {
unique_lock<std::mutex> lk(m);
cv.wait(lk);
cout << numbers.front() << endl;
numbers.pop();
consumer_count++;
}
}
int main() {
condition_variable cv;
mutex m;
bool workdone = false;
queue<int> numbers;
//start threads
thread producer(generateNumbers, ref(numbers), ref(cv), ref(m), ref(workdone));
thread consumer(work, ref(numbers), ref(cv), ref(m), ref(workdone));
//wait for 3 seconds, then join the threads
this_thread::sleep_for(std::chrono::seconds(3));
workdone = true;
producer.join();
consumer.join();
//output the counters
cout << producer_count << endl;
cout << consumer_count << endl;
return 0;
}
大家好, 我尝试用 C++ 实现生产者-消费者模式。 生产者线程生成随机整数,将它们添加到队列中,然后通知消费者线程添加了新数字。
消费者线程等待通知,然后将队列的第一个元素打印到控制台并删除它。
我为添加到队列中的每个数字增加一个计数器,并为从队列中取出的每个数字增加一个计数器。
我希望两个计数器在程序完成后保持相同的值,但是差异很大。 代表加入队列的计数器始终在百万范围内(我上次测试中为 3871876),代表消费者从队列中取出数字的计数器始终低于 100k(我上次测试中为 89993)。
有人可以向我解释为什么会有如此巨大的差异吗? 我是否必须添加另一个条件变量,以便生产者线程也等待消费者线程? 谢谢!
【问题讨论】:
-
可能是生产者比消费者快一点,并且差异是由于线程加入后
numbers正好有producer_count - consumer_count元素造成的吗?std::cout << numbers.front() << std::endl;涉及大量工作,尤其是因为您不必要地 (?) 刷新每个数字的输出。 -
不应该
workdone是atomic<bool>之类的吗? -
生产者和消费者之间存在竞争条件。恰好生产者比消费者更频繁地获取锁。
-
删除“工作”函数中的“while(!workdone)”。然后你会得到预期的结果。因为您希望队列为空。现在只有以下情况成立:producer_count == consumer_count + numbers.size()。
-
尝试
while (!(workdone && numbers.empty()))让消费者继续,直到它应该退出并且队列为空。也许这就是你想要的行为。
标签: c++ multithreading condition-variable