C++ 同步队列
我正在尝试实现队列以同步生产者-消费者问题。但是,我不明白为什么我的解决方案会死锁 它应该做什么: 对于包含使用者线程任务的固定大小队列,应阻止生产者,直到队列中有空间为止。(m生产者,n消费者) 技术要求:POSIX线程(无C++11)C++ 同步队列,c++,multithreading,data-structures,pthreads,producer-consumer,C++,Multithreading,Data Structures,Pthreads,Producer Consumer,我正在尝试实现队列以同步生产者-消费者问题。但是,我不明白为什么我的解决方案会死锁 它应该做什么: 对于包含使用者线程任务的固定大小队列,应阻止生产者,直到队列中有空间为止。(m生产者,n消费者) 技术要求:POSIX线程(无C++11) void任务生成器(ArData&a){ while(true){ 工时=a.工时生成器(); 如果(工时==NULL){ a、 queue.finished(); 返回; } 工作任务; a、 队列推送(任务); } } 无效使用者(任务队列和队列){ wh
void任务生成器(ArData&a){
while(true){
工时=a.工时生成器();
如果(工时==NULL){
a、 queue.finished();
返回;
}
工作任务;
a、 队列推送(任务);
}
}
无效使用者(任务队列和队列){
while(true){
Task=queue.pop();
if(task.end)返回;
task.run();
}
}
#定义\u生产者的数量\u 2
//任务ktery muze vlakno zpracovat
课堂任务{
公众:
Task():end(false){}
//执行任务
虚拟空运行(){}
//将任务标记为结束任务,使用者应退出线程
布尔端;
};
//同步队列
类任务队列{
私人:
//使用者线程数
国际消费者协会;
//完成生产的生产商数量
int doneProducers;
//生产者等待,消费者发帖
sem_t生产通知人;
//消费者等待,生产者发帖
sem_t消费者通知;
//整个TaskQueue的互斥锁
pthread_mutex_t mut;
//数据存储
std::队列;
公众:
显式任务队列(int m_numoConsumers):numoConsumers(m_numoConsumers),doneProducers(0){
pthread_mutex_t mut;
pthread_mutex_init(&mut,NULL);
sem_init(&consumerNotificator,0,0);
sem_init(&生产通知人,0,数量*10);
}
~TaskQueue(){
pthread_mutex_destroy(&mut);
sem_销毁(和消费者通知);
sem_销毁(和生产通知);
}
//在推之前等待队列中的空插槽
无效推送(任务和任务){
//等待队列中的插槽
sem_wait(和生产通知人);
//在任何操作之前锁定
pthread_mutex_lock(&mut);
队列推送(任务);
pthread_mutex_unlock(&mut);
//通知消费者等待任务
sem_post(和消费者通知);
}
//等待项目进入队列并弹出它
任务pop(){
//等待队列中的任务
sem_wait(和消费者通知);
//在任何操作之前锁定
pthread_mutex_lock(&mut);
Task=queue.front();
queue.pop();
pthread_mutex_unlock(&mut);
//通知生产者队列中的插槽为空
sem_职位(和生产通知人);
返回任务;
}
//处理整理生产商
作废已完成(){
//在任何操作之前锁定
pthread_mutex_lock(&mut);
//检查它是否不是最后一个生产者
if(生产者数量>++生产者){
pthread_mutex_unlock(&mut);
返回;
}
//若它是最后一个生产者,那个么通过将结束任务添加到队列中最终消费者
对于(int i=0;i
据我所知,当第二个生产者调用
finished
时,它在pthread\u mutex\u lock(&mut)处死锁代码>。不知道为什么。pthread\u mutex\u t mut代码>-在构造函数中隐藏相同名称的成员变量,该变量保持未初始化状态。这可能不是故意的。为了防止这种名称冲突,最好为私有成员变量使用特殊名称。我更喜欢在这里使用下划线后缀,例如,pthread\u mutex\u t mut代码>。谢谢,那真是个愚蠢的错误。否则代码是否正确?如果您根据您的评论创建答案,我将接受。
void taskProducer(ArData &a) {
while (true) {
Work work = a.workGenerator();
if (work == NULL) {
a.queue.finished();
return;
}
WorkTask task(work);
a.queue.push(task);
}
}
void consumer(TaskQueue &queue) {
while (true) {
Task task = queue.pop();
if (task.end) return;
task.run();
}
}
#define NUM_OF_PRODUCERS 2
//Task ktery muze vlakno zpracovat
class Task {
public:
Task() : end(false){ }
//Execute task
virtual void run() { }
//Mark task as ending Task, consumer should exit thread
bool end;
};
//Synchronous queue
class TaskQueue {
private:
//Number of consumer threads
int numOfConsumers;
//Number of producers that finished producing
int doneProducers;
//Producers wait, Consumers post
sem_t producerNotificator;
//Consumers wait, Producers post
sem_t consumerNotificator;
//Mutex for entire TaskQueue
pthread_mutex_t mut;
//Data storage
std::queue<Task> queue;
public:
explicit TaskQueue(int m_numOfConsumers) : numOfConsumers(m_numOfConsumers), doneProducers(0) {
pthread_mutex_t mut;
pthread_mutex_init(&mut, NULL);
sem_init(&consumerNotificator, 0, 0);
sem_init(&producerNotificator, 0, numOfConsumers *10);
}
~TaskQueue() {
pthread_mutex_destroy(&mut);
sem_destroy(&consumerNotificator);
sem_destroy(&producerNotificator);
}
//Waits for empty slot in queue before pushing
void push(Task &task) {
//Wait for slot in queue
sem_wait(&producerNotificator);
//Lock before any manipulation
pthread_mutex_lock(&mut);
queue.push(task);
pthread_mutex_unlock(&mut);
//Notify consumer of waiting Task
sem_post(&consumerNotificator);
}
//Waits before item is in queue and pops it
Task pop() {
//Wait for Task in queue
sem_wait(&consumerNotificator);
//Lock before any manipulation
pthread_mutex_lock(&mut);
Task task = queue.front();
queue.pop();
pthread_mutex_unlock(&mut);
//Notify producer about empty slot in queue
sem_post(&producerNotificator);
return task;
}
//Handle finishing producers
void finished() {
//Lock before any manipulation
pthread_mutex_lock(&mut);
//Check if it is not last producer
if (NUM_OF_PRODUCERS > ++doneProducers) {
pthread_mutex_unlock(&mut);
return;
}
//If it was last producer end consumers by adding end tasks into queue
for (int i = 0; i < numOfConsumers; ++i) {
Task t;
t.end = true;
queue.push(t);
}
pthread_mutex_unlock(&mut);
//Notify all consumers about new Tasks
for (int i = 0; i < numOfConsumers; ++i) {
sem_post(&consumerNotificator);
}
}
};