C++生产者消费者陷入僵局
C++ Producer Consumer stuck in deadlock
我正在尝试创建一个生产者-消费者程序,其中消费者必须继续运行,直到所有生产者都完成,然后消费队列中剩余的内容(如果还有剩余的话(,然后结束。您可以在下面检查我的代码,我想我知道问题(可能是死锁(在哪里,但我不知道如何使其正常工作。
#include<iostream>
#include<cstdlib>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
class Company{
public:
Company() : producers_done(false) {}
void start(int n_producers, int n_consumers); // start customer&producer threads
void stop(); // join all threads
void consumer();
void producer();
/* some other stuff */
private:
condition_variable cond;
mutex mut;
bool producers_done;
queue<int> products;
vector<thread> producers_threads;
vector<thread> consumers_threads;
/* some other stuff */
};
void Company::consumer(){
while(!products.empty()){
unique_lock<mutex> lock(mut);
while(products.empty() && !producers_done){
cond.wait(lock); // <- I think this is where the deadlock happens
}
if (products.empty()){
break;
}
products.pop();
cout << "Removed product " << products.size() << endl;
}
}
void Company::producer(){
while(true){
if((rand()%10) == 0){
break;
}
unique_lock<mutex> lock(mut);
products.push(1);
cout << "Added product " << products.size() << endl;
cond.notify_one();
}
}
void Company::stop(){
for(auto &producer_thread : producers_threads){
producer_thread.join();
}
unique_lock<mutex> lock(mut);
producers_done = true;
cout << "producers done" << endl;
cond.notify_all();
for(auto &consumer_thread : consumers_threads){
consumer_thread.join();
}
cout << "consumers done" << endl;
}
void Company::start(int n_producers, int n_consumers){
for(int i = 0; i<n_producers; ++i){
producers_threads.push_back(thread(&Company::producer, this));
}
for(int i = 0; i<n_consumers; ++i){
consumers_threads.push_back(thread(&Company::consumer, this));
}
}
int main(){
Company c;
c.start(2, 2);
c.stop();
return true;
}
我知道,这里有很多与生产者-消费者相关的问题,我已经滚动了其中的至少 10 个,但没有一个能回答我的问题。
当人们将std::atomic
与std::mutex
一起使用时,std::condition_variable
几乎100%会导致死锁。这是因为对该原子变量的修改不受互斥锁的保护,因此在互斥锁锁定后但在条件变量等待使用者之前更新该变量时,条件变量通知会丢失。
解决方法是不使用std::atomic
,只在持有互斥锁时修改和读取producers_done
。 例如:
void Company::consumer(){
for(;;){
unique_lock<mutex> lock(mut);
while(products.empty() && !producers_done)
cond.wait(lock);
if(products.empty())
break;
orders.pop();
}
}
代码中的另一个错误是,在while(!products.empty())
中,它会在不持有互斥锁的情况下调用products.empty()
,从而导致争用条件。
下一个错误是在等待使用者线程终止时保持互斥锁锁定。修复:
{
unique_lock<mutex> lock(mut);
producers_done = true;
// mutex gets unlocked here.
}
cond.notify_all();
for(auto &consumer_thread : consumers_threads)
consumer_thread.join();
相关文章:
- 消费者和生产者问题的双重缓冲
- 如何降低生产者获得锁的可能性,而消费者在使用std::condition_variable时无法获得锁?
- C++ deque 消费者总是从生产者那里得到空队列
- localtime() 函数正在调用 ___lll_lock_wait_private(),这会使线程陷入死锁
- 广度优先搜索陷入无限循环
- 陷入输入C++的无限循环中
- C++多线程生产者-消费者问题
- 生产者和消费者优化
- 如何查看Tibco EMS独享队列是否有活跃消费者?
- 陷入无限循环(骑士巡回赛问题)
- OpenSSL客户端陷入无休止的读取
- 特定的生产者-消费者方案
- 为什么condition_variable在等待生产者-消费者的锁定?C++
- 卡夫卡消费者投票最新消息
- 为什么 boost interprocess_condition notify_one陷入僵局?
- 将生产者/消费者与障碍同步
- 任何用于PostgreSQL的OLE DB提供商/消费者
- C++生产者消费者陷入僵局
- 生产者,消费者和我可爱的僵局
- Visual C++开关控制路径陷入僵局