如何避免在c ++中的一些繁重处理期间阻塞线程?

时间:2016-06-07 04:09:14

标签: c++ multithreading c++11 thread-safety pthreads

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

所以我的问题是,

  1. 我不想阻止Hoge :: update()。所以在存储数据之后,我不想使用th_process_data.join()。有没有更好的解决方案?
  2. 在另一个线程中处理数据后,如何将此处理后的数据返回给Hoge实例。一些回调类是解决方案吗?
  3. 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)
    }
    

1 个答案:

答案 0 :(得分:1)

你的部分Q对我来说并不是很清楚,因为它看起来很开放很多可能性。但是你的2个查询是客观的,因此我试图回答我最近使用套接字的经验。

  

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

在这种情况下,你可以这样做:

th_process_data.detach();

这样可以免除.join()上的阻止。如果您的设计允许,您也可以使用std::futurestd::promise组合。有关详细信息,请参阅this post

  

“2。在另一个线程中处理data之后,如何将此处理过的数据返回给Hoge实例。某些回调类是解决方案吗?”

我没有看到简单地调用Hoge::on_received()方法并传递data。该主题仅为th_process_data。如果您担心提供时间切片并使用sleep_for()方法,那么您也可以寻找std::yield作为替代方案。

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