如何避免在c++中进行一些繁重的处理时阻塞线程

How to avoid blocking thread during some heavy processing in c++?

本文关键字:处理 线程 c++ 何避免      更新时间:2023-10-16

我是c++多线程程序的初学者。我为我的问题创建了一个伪代码。Hoge类是连接套接字的通信类,我假设Hoge::update()是通过套接字接收数据的类。如果特定的数据已经到达,则Hoge实例将数据传递给Fuga实例进行specificc处理。

所以我的问题是,

  1. 我不想阻止Hoge::update()。所以在存储数据之后,我不想使用th_process_data.join()。有更好的解决方案吗
  2. 在另一个线程中处理数据后,如何将处理后的数据返回给Hoge实例。某个回调类是解决方案吗

Hoge.cc

Fuga fuga;
Hoge::update() {
while(true) {
if(check_something()) {
auto data = get_data();
fuga.push_data(data);
}
}
}
Hoge::on_received(const Data& data) {
std::cout << "received: " << data.id << std::endl;
// do something...
}

Fuga.cc

std::vector<Data> data_list;
std::mutex mtx;
Fuga::push_data(const Data& data) {
{
std::lock_guard<std::mutex> lock(mtx);
data_list.push_back(data);
}
std::thread th_process_data([&]{ do_processing(); });
// Q1. I don't want to block this thread for Hoge::update()
}
Fuga::do_processing() {
Data data;
{
std::lock_guard<std::mutex> lock(mtx);
data = data_list.pop();
}
// heavy task for data...
std::this_thread::sleep_for(std::chrono::seconds(3)); 
// Q2. How to pass this processed data to Hoge::on_received(const Data& data)
}

我不太清楚你的Q的一部分,因为它似乎有很多可能性。然而,您的两个问题是客观的,因此我试图根据我最近使用套接字的经验来回答。

"1.我不想阻止Hoge::update()。所以在存储数据后,我不想使用th_process_data.join()。有更好的解决方案吗?">

在这种情况下,您可以执行:

th_process_data.detach();

这将使您免于在.join()上被阻止。如果您的设计允许,您也可以使用std::futurestd::promise组合。更多信息可以在这篇文章中找到。

"2.在另一个线程中处理data后,如何将处理后的数据返回到Hoge实例。一些回调类是解决方案?">

我认为简单地调用Hoge::on_received()方法并传递data没有什么大不了的。线程将仍然只是th_process_data。如果您担心提供时间切片并使用sleep_for()方法,那么您也可以寻找std::yield作为替代方案。


根据您当前的设计,您已经在两种方法中放置了2个std::mutex。我觉得,这不是必须的
此外,请记住,每次调用Fuga::push_data()时,都会创建一个thread。如果频繁调用此方法,并且您不想以创建多个线程为代价来加载CPU,那么最好创建一次单个线程,并在其中等待数据的接收。但这需要改变设计。