问题是生产者线程没有等待,我希望生产者线程等待消费者线程,直到消费者完成处理4000个项目,一旦完成,它将通知生产者线程,然后生产者线程可以继续下一批。
我在这里做错了什么?
另一个问题是,批次中并不总是有4000个项目。 ESP。如果你采取最后一批。在这种情况下,Produce线程应通知Consumer线程完成<deque>
#include <windows.h>
#include <string>
#include <iostream>
#include <deque>
#include <chrono>
#include <thread>
#include <boost/scoped_ptr.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
using namespace std;
using namespace boost;
boost::mutex ResponseMutex;
boost::condition_variable qFull, qEmpty;
class A
{
private:
boost::thread* myProducerThread;
boost::thread* myConsumerThread;
public:
A()
{
myProducerThread = nullptr;
myConsumerThread = nullptr;
}
void RunThreads();
void RunProducer();
void RunConsumer();
void ProducerWait();
void ConsumerWait();
struct Record
{
char response[128];
Record(const char* response)
{
memset(this->response,0,sizeof(this->response));
strcpy(this->response, response);
}
~Record()
{
}
Record& operator= (const Record& cmd)
{
if(this == &cmd) // Same object?
{
return *this;
}
memset(this->response,0,sizeof(this->response));
strcpy(this->response, cmd.response);
return *this;
}
};
typedef deque<Record> RecordsQueue;
};
A::RecordsQueue Records;
void A::RunThreads()
{
myProducerThread = new boost::thread(boost::bind(&A::RunProducer, this));
HANDLE threadHandle1 = myProducerThread->native_handle();
SetThreadPriority(threadHandle1, THREAD_PRIORITY_NORMAL);
myConsumerThread = new boost::thread(boost::bind(&A::RunConsumer, this));
HANDLE threadHandle2 = myConsumerThread->native_handle();
SetThreadPriority(threadHandle2, THREAD_PRIORITY_NORMAL);
myProducerThread->join();
myConsumerThread->join();
}
void A::ProducerWait()
{
boost::mutex::scoped_lock lock(ResponseMutex);
while(!Records.empty())
{
qEmpty.wait(lock);
}
}
void A::ConsumerWait()
{
boost::mutex::scoped_lock lock(ResponseMutex);
while(Records.size() <= 4000)
{
qFull.wait(lock);
}
}
void A::RunProducer()
{
int i = 0;
while(true)
{
ProducerWait();
vector<string> responses;
responses.push_back(to_string(i));
cout<< "Added: " << to_string(i) << endl;
i++;
qFull.notify_one();
}
}
void A::RunConsumer()
{
while(true)
{
ConsumerWait();
Record res = Records.front();
cout<< "Processed: " << res.response << endl;
Records.pop_front();
qEmpty.notify_one();
}
}
int main()
{
A a;
a.RunThreads();
}
答案 0 :(得分:2)
while (true) {
std::vector<std::string> responses;
responses.push_back(std::to_string(i));
qFull.notify_one();
}
您不会分享回复。消费者将如何看待响应向量?它将在每次循环迭代开始时为空。
另外
接下来:您的条件是这样的,即在发布1个工作项(记录)后,您将等到消费者消耗4000个。我不知道它是如何工作的。
为什么不在生产者方面累积4000件物品,然后将其交给消费者?这样,您实际上可以从线程中受益。想一想:你有两个线程:一个是等待创建4000个作业,另一个是等待第一个完全清空队列。你在这里得到的是带有很多噪音和不必要的锁争用的美化顺序代码。
在这里使用我的水晶球是一个修复上述大部分内容的版本(包括缺少锁定,考虑虚假唤醒等)。
您仍然需要修复
strcpy
的不安全使用 !!!
#include <string>
#include <iostream>
#include <deque>
#include <chrono>
#include <thread>
#include <boost/scoped_ptr.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
static constexpr auto MIN_QUEUE_WORK = 10;
static constexpr auto MAX_QUEUE_WORK = 40; // 4000;
class A {
private:
boost::thread myProducerThread;
boost::thread myConsumerThread;
boost::mutex mutex_;
boost::condition_variable pushed_, popped_;
struct Record {
char response[128];
Record(const char *response) {
memset(this->response, 0, sizeof(this->response));
strcpy(this->response, response);
}
~Record() {}
Record &operator=(const Record &cmd) {
if (this == &cmd) // Same object?
{
return *this;
}
memset(this->response, 0, sizeof(this->response));
strcpy(this->response, cmd.response);
return *this;
}
};
typedef std::deque<Record> RecordsQueue;
RecordsQueue queue_;
public:
void RunThreads();
void RunProducer();
void RunConsumer();
};
void A::RunThreads() {
myProducerThread = boost::thread(&A::RunProducer, this);
myConsumerThread = boost::thread(&A::RunConsumer, this);
myProducerThread.join();
myConsumerThread.join();
}
void A::RunProducer() {
int i = 0;
while (i<1000) {
boost::mutex::scoped_lock lock(mutex_);
popped_.wait(lock, [this] { return queue_.size()<MAX_QUEUE_WORK; });
queue_.push_back(Record { std::to_string(i).c_str() });
std::cout << "Added: " << std::to_string(i) << " size: " << queue_.size() << std::endl;
i++;
pushed_.notify_one();
}
}
void A::RunConsumer() {
while (true) {
boost::mutex::scoped_lock lock(mutex_);
pushed_.wait(lock, [this]{return queue_.size()>MIN_QUEUE_WORK;});
Record res = queue_.front();
std::cout << "Processed: " << res.response << std::endl;
queue_.pop_front();
popped_.notify_one();
}
}
int main() {
A a;
a.RunThreads();
}