我想解决多个生产者单个消费者问题,以下代码在无限循环中显示一个生产者和一个消费者线程(我这样做是为了测试我的代码)但是它提供了错误的数据输出然后分割一段时间后出现故障这是我试过的代码:
#include<iostream>
#include<mutex>
#include<condition_variable>
#include<malloc.h>
#include<unistd.h>
#include<thread>
#include<assert.h>
#define QUEUE_SIZE 100
using namespace std;
struct node
{
int data;
};
template<class T, unsigned long Q_SIZE = QUEUE_SIZE>
class NaiveQueue {
private:
static const unsigned long Q_MASK = Q_SIZE - 1;
unsigned long head_, tail_;
std::condition_variable cond_empty_;
std::condition_variable cond_overflow_;
std::mutex mtx_;
T **ptr_array_;
public:
NaiveQueue(): head_(0), tail_(0)
{
ptr_array_ = (T **)::memalign(getpagesize(),Q_SIZE * sizeof(void *));
assert(ptr_array_);
}
void push(T *x)
{
std::unique_lock<std::mutex> lock(mtx_);
cond_overflow_.wait(lock, [this]() {
return tail_ + Q_SIZE > head_;
});
ptr_array_[head_++ & Q_MASK] = x;
cond_empty_.notify_one();
}
T* pop()
{
std::unique_lock<std::mutex> lock(mtx_);
cond_empty_.wait(lock, [this]() {
return tail_ < head_;
});
T *x = ptr_array_[tail_++ & Q_MASK];
cond_overflow_.notify_one();
return x;
}
};
void producer(NaiveQueue<node> &obj)
{
while(1)
{
node *temp;
temp=new node();
temp->data=10;
obj.push(temp);
cout<<"\nPushed : "<<10;
}
}
void consumer(NaiveQueue<node> &obj)
{
while(1)
{
node *temp;
temp=NULL;
temp=obj.pop();
if(temp)
{
cout<<"\nRemoved : "<<temp->data;
delete temp;
}
}
}
int main()
{
NaiveQueue<node> obj;
thread t1(producer,ref(obj));
thread c1(consumer,ref(obj));
t1.join();
c1.join();
return 0;
}
生成此输出:
Pushed :
Removed : 1010
Pushed : 10
Pushed : 10
Pushed : 10
Pushed : 10
Removed : 10
Removed : 10
Removed : 10
Removed : 10
Removed : 10
Pushed : 10
Pushed : 10
Pushed : 10
Pushed : 10
Pushed : 10
Pushed : 10
Pushed : 10
Pushed : 10
Pushed : 10
Pushed : 10
Pushed : 10
Pushed : 10
Pushed : 10
Pushed : 10
Pushed : 10
Pushed : 10
Pushed :
Removed : 1010
Pushed : 10
Pushed : 10
Pushed : 10
Pushed : 10
Pushed : 10
Pushed : 10
Pushed : 10
Removed : 10
Removed : 10
Removed : 10
Removed : 10
Removed : 10
Removed : -1140848048
Removed : -1140847792
Removed : -1140847760
Removed : -1140847856
Removed : -1140847824
Removed : -1140847792
Removed : -1140847760
Removed : -1140847856
Removed : -1140847824
Removed : -1140847792
Removed : -1140847760
Removed : -1140847856
Removed : -1140847824
Removed : -1140847792
Removed : -1140847760
Removed : -1140847856
Removed : -1140847824
Removed : -1140847792
Pushed : 10
Pushed :
Removed : 1010
Pushed : 10
Pushed : 10
Pushed : 10
Pushed : 10
Pushed : 10
Segmentation fault
我哪里出错了?为什么-1140847856
在第一时间没有被删除时被删除。
答案 0 :(得分:1)
您的等待条件和指数计算错误:
让
Q_SIZE =10, Q_MASK=9, tail_=2,head_=5
然后
tail_ + Q_SIZE > head_
将是真的,它会推送
head_++ & Q_MASK = 5 & 9 = 1th index
这是错误的。
何时
tail_=0, head_= 9
然后
tail_ + Q_SIZE > head_
将是真的,它会推动
head_++ & Q_MASK = 9 & 9 = 9th index
但队列已满,推送应该等到tail_
变为1
,即至少弹出一个项目。
弹出时tail_ < head_
也是错误的条件。
大概你可以这样做(未经测试)
void push(T *x)
{
std::unique_lock<std::mutex> lock(mtx_);
cond_overflow_.wait(lock, [this]() {
return abs( head_ - tail_ )< Q_SIZE ;
});
ptr_array_[head_ ] = x;
head_ = (++head) % Q_SIZE;
cond_empty_.notify_one();
}
T* pop()
{
std::unique_lock<std::mutex> lock(mtx_);
cond_empty_.wait(lock, [this]() {
return abs(head_ - tail_)>0;
});
T *x = ptr_array_[tail_];
tail_ = (++tail_)% Q_SIZE;
cond_overflow_.notify_one();
return x;
}