C++ 同步队列

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

我正在尝试实现队列以同步生产者-消费者问题。但是,我不明白为什么我的解决方案会死锁

它应该做什么: 对于包含使用者线程任务的固定大小队列,应阻止生产者,直到队列中有空间为止。(m生产者,n消费者)

技术要求:POSIX线程(无C++11)

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);
            }
        }
    };