c++ 11简单生产者消费者多线程



我正在尝试教自己多线程,我遵循这个教程在这里:https://www.classes.cs.uchicago.edu/archive/2013/spring/12300-1/labs/lab6/

如果你一直滚动到底部,有一个生产者-消费者的示例片段,它要求我们解决以下代码中的竞争条件:

#include <iostream>
#include <thread>
#include <condition_variable>
#include <mutex>
#include <chrono>
#include <queue>
using namespace std;
int main() {
int c = 0;
bool done = false;
queue<int> goods;
thread producer([&]() {
for (int i = 0; i < 500; ++i) {
goods.push(i);
c++;
}
done = true;
});
thread consumer([&]() {
while (!done) {
while (!goods.empty()) {
goods.pop();
c--;
}
}
});
producer.join();
consumer.join();
cout << "Net: " << c << endl;
}

最后的净值应该是0,这是我的尝试:

#include <iostream>
#include <thread>
#include <condition_variable>
#include <mutex>
#include <chrono>
#include <queue>
#include <atomic>
using namespace std;

int main() {
int c = 0;
bool done = false;
queue<int> goods;
mutex mtx;  
condition_variable cond_var;
// thread to produce 500 elements
thread producer([&]() {
for (int i = 0; i < 500; ++i) {
// lock critical secion
unique_lock<mutex> lock(mtx);   
goods.push(i);
c++;
lock.unlock();
// notify consumer that data has been produced
cond_var.notify_one();
}
// notify the consumer that it is done
done = true;
cond_var.notify_one();

});
// thread to consume all elements
thread consumer([&]() {
while (!done) {
unique_lock<mutex> lock(mtx);   
while (!goods.empty()) {
goods.pop();
c--;
}
// unlocks lock and wait until something in producer gets put
cond_var.wait(lock);
}
});
producer.join();
consumer.join();
cout << "Net: " << c << endl;
}

我觉得我基本上错过了一些东西。我认为我遇到的最大问题是cond_var。wait()的消费者因为如果生产者设置了"完成"为true则消费者不会返回while(!goods.empty())。我不知道如何解决这个问题。

任何提示,解释或甚至不同的方法将不胜感激!

制片人:

thread producer([&]() {
for (int i = 0; i < 500; ++i)
{
{
// Just have a lock while interacting with shared items.
unique_lock<mutex> lock(mtx);   
goods.push(i);
c++;
}
cond_var.notify_one();
}
// Lock to update shared state.
unique_lock<mutex> lock(mtx);   
done = true;
cond_var.notify_one();
});
消费者
thread consumer([&]() {
// This loop exits when
//        done          => true
//   AND  goods.empty() => true
// Acquire lock before checking shared state.
unique_lock<mutex> lock(mtx);
while (!(done && goods.empty()))
{
// Wait until there is something in the queue to processes
// releasing lock while we wait.
// Break out if we are done or goods is not empty.
cond_var.wait(lock, [&](){return done || !goods.empty();});
// You now have the lock again, so modify shared state is allowed
// But there is a possibility of no goods being available.
// So let's check before doing work.
if (!goods.empty())
{
goods.pop();
c--;
}
}
});

如果我们只是解决竞争条件。我们可以简单地检查done的状态,并确保没有其他变量有相互作用。

制作人:

thread producer([&]() {
// The consumer is not allowed to touch goods
// until you are finished. So just use with
// no locks.
for (int i = 0; i < 500; ++i)
{
goods.push(i);
c++;
}
// Lock to update shared state.
// Tell consumer we are ready for processing.
unique_lock<mutex> lock(mtx);   
done = true;
cond_var.notify_one();
});
消费者
thread consumer([&]() {
// Acquire lock before checking shared state.
unique_lock<mutex> lock(mtx);
cond_var.wait(lock, [&](){return done;});
// We now know the consumer has finished all updates.
// So we can simply loop over the goods and processes them
while (!goods.empty())
{
goods.pop();
c--;
}
});

最新更新