I\'m trying to create a producer-consumer program, where the consumers must keep running until all the producers are finished, then consume what\'s left in the queue (if the
When people use std::atomic
along with std::mutex
and std::condition_variable
that results in deadlock in almost 100% of cases. This is because modifications to that atomic variable are not protected by the mutex and hence condition variable notifications get lost when that variable is updated after the mutex is locked but before condition variable wait in the consumer.
A fix would be to not use std::atomic
and only modify and read producers_done
while the mutex is held. E.g.:
void Company::consumer(){
for(;;){
unique_lock<mutex> lock(mut);
while(products.empty() && !producers_done)
cond.wait(lock);
if(products.empty())
break;
orders.pop();
}
}
Another error in the code is that in while(!products.empty())
it calls products.empty()
without holding the mutex, resulting in a race condition.
The next error is keeping the mutex locked while waiting for the consumer threads to terminate. Fix:
{
unique_lock<mutex> lock(mut);
producers_done = true;
// mutex gets unlocked here.
}
cond.notify_all();
for(auto &consumer_thread : consumers_threads)
consumer_thread.join();