gpt4 book ai didi

c++ - C++生产者使用者陷入僵局

转载 作者:行者123 更新时间:2023-12-02 10:36:31 24 4
gpt4 key购买 nike

我正在尝试创建一个生产者-消费者程序,在该程序中,消费者必须继续运行,直到所有生产者都完成为止,然后消费队列中剩余的内容(如果还有剩余),然后结束。您可以在下面检查我的代码,我想我知道问题出在哪里(可能是死锁),但是我不知道如何使其正常工作。

  #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::atomicstd::mutexstd::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();

关于c++ - C++生产者使用者陷入僵局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60037047/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com