C++ 制作人及;使用条件变量的使用者线程
问题是生产者线程不等待,我希望生产者线程等待消费者线程,直到消费者完成处理4000个项目,一旦完成,它将通知生产者线程,然后生产者线程可以继续下一批 我做错了什么 另一个问题是,一批中并不总是有4000个项目。特别是如果你吃最后一批。在这种情况下,product线程应该通知Consumer线程完成C++ 制作人及;使用条件变量的使用者线程,c++,multithreading,boost,C++,Multithreading,Boost,问题是生产者线程不等待,我希望生产者线程等待消费者线程,直到消费者完成处理4000个项目,一旦完成,它将通知生产者线程,然后生产者线程可以继续下一批 我做错了什么 另一个问题是,一批中并不总是有4000个项目。特别是如果你吃最后一批。在这种情况下,product线程应该通知Consumer线程完成 #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 使用名称空间std; 使用名称空间boost; boost::互斥应答; boost::条件变量qFull,qEmpty; 甲级
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
使用名称空间boost;
boost::互斥应答;
boost::条件变量qFull,qEmpty;
甲级
{
私人:
boost::thread*myProducerThread;
boost::线程*myConsumerThread;
公众:
()
{
myProducerThread=nullptr;
myConsumerThread=nullptr;
}
void RunThreads();
void RunProducer();
void RunConsumer();
无效生产商();
使无效,使无效();
结构记录
{
字符响应[128];
记录(常量字符*响应)
{
memset(this->response,0,sizeof(this->response));
strcpy(这个->响应,响应);
}
~Record()
{
}
记录和运算符=(常量记录和命令)
{
if(this==&cmd)//同一个对象?
{
归还*这个;
}
memset(this->response,0,sizeof(this->response));
strcpy(此->响应,命令响应);
归还*这个;
}
};
typedef-deque-recordsque;
};
A::RecordsQueue记录;
void A::RunThreads()
{
myProducerThread=newboost::thread(boost::bind(&A::RunProducer,this));
HANDLE threadHandle1=myProducerThread->native_HANDLE();
设置ThreadPriority(threadHandle1,THREAD_PRIORITY_NORMAL);
myConsumerThread=newboost::thread(boost::bind(&A::RunConsumer,this));
HANDLE threadHandle2=myConsumerThread->native_HANDLE();
设置ThreadPriority(threadHandle2,THREAD_PRIORITY_NORMAL);
myProducerThread->join();
myConsumerThread->join();
}
void A::ProducerWait()
{
boost::mutex::作用域锁定(ResponseMutex);
而(!Records.empty())
{
qEmpty.wait(lock);
}
}
void A::ConsumerWait()
{
boost::mutex::作用域锁定(ResponseMutex);
虽然(Records.size()是我的错,但实际上我修改了一个现有的示例。让我更正源代码。我将编辑此帖子。@user3924882哦。对了:(我希望你知道,如果你再细心一点,你将来就更有可能得到帮助。这是我对你似乎在寻找的东西的想法。祝你有愉快的一天!我总是喜欢你的答案,你的帖子。很好的学习经验。谢谢。你不需要使用bind
来创建线程,为什么你要动态地分配线程你的线程?如果你不使用new
创建它们,你不会忘记删除它们。你的代码不是线程安全的,你只锁定ConsumerWait()范围内的互斥锁,然后不加锁定地访问Records
成员。这很好。我没有提到它,尽管我的示例代码也修复了这一点:)更不用说strcpy了。我不确定我是否想要这个代码/除了学习(可能)?
#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();
}
while (true) {
std::vector<std::string> responses;
responses.push_back(std::to_string(i));
qFull.notify_one();
}
#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();
}