我正在尝试实现队列以同步生产者 - 消费者问题。但是我无法弄清楚为什么我的解决方案会死锁。
它应该做什么: 具有固定大小的队列包含用户线程的任务,生产者应该被阻塞,直到队列中有空间为止。 (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);
处死锁。不知道为什么。