同步队列

时间:2016-03-29 16:13:29

标签: c++ multithreading data-structures pthreads producer-consumer

我正在尝试实现队列以同步生产者 - 消费者问题。但是我无法弄清楚为什么我的解决方案会死锁。

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

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

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

据我所知,当第二个制作人调用finished时,它会在pthread_mutex_lock(&mut);处死锁。不知道为什么。

0 个答案:

没有答案