首页 > 解决方案 > 了解多线程如何与 Boost io_service 一起工作

问题描述

我正在学习多线程和 Boost 库(尤其是 Asio),我很难理解以下代码是如何工作的(从 Boost.org 教程略有修改)

#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>

class printer
{
public:
  printer(boost::asio::io_service& io)
    : timer1_(io, boost::posix_time::seconds(1)),
      timer2_(io, boost::posix_time::seconds(1)),
      count_(0)
  {
    timer1_.async_wait(boost::bind(&printer::print1, this));

    timer2_.async_wait(boost::bind(&printer::print2, this));
  }

  ~printer()
  {
    std::cout << "Final count is " << count_ << std::endl;
  }

  void print1()
  {
    if (count_ < 10)
    {
      std::cout << "Timer 1: " << count_ << std::endl;
      ++count_;

      timer1_.expires_at(timer1_.expires_at() + boost::posix_time::seconds(2));

      timer1_.async_wait(boost::bind(&printer::print1, this));
    }
  }

  void print2()
  {
    if (count_ < 10)
    {
      std::cout << "Timer 2: " << count_ << std::endl;
      ++count_;

      timer2_.expires_at(timer2_.expires_at() + boost::posix_time::seconds(2));

      timer2_.async_wait(boost::bind(&printer::print2, this));
    }
  }

private:
  boost::asio::deadline_timer timer1_;
  boost::asio::deadline_timer timer2_;
  int count_;
};

void saysomething()
{
    std::string whatyasay;
    std::cin >> whatyasay;
    std::cout << "You said " << whatyasay << std::endl;
}
int main()
{
  boost::asio::io_service io;
  printer p(io);
  boost::thread t(boost::bind(&boost::asio::io_service::run, &io));
  io.run();
  std::cout << "Hey there\n";
  t.join();

  return 0;
}

导致以下输出

Timer 1: 0
Timer 2: 1
Timer 1: 2
Timer 2: 3
Timer 1: 4
Timer 2: 5
Timer 1: 6
Timer 2: 7
Timer 1: 8
Timer 2: 9
Hey there
Final count is 10

我对这段代码的期望是线程 t 将负责运行 io_service,这意味着其他操作可能同时发生。

相反,代码的行为与往常一样,也就是 io.run “阻塞”代码流,直到打印机对象内的计时器停止启动 async_waits,因此只有在计时器不再工作后才会打印“嘿,那里”。

但这还不是全部:据我了解,只要有与之相关的工作(无论是工作对象,或者在本例中为计时器),调用 run() 方法后 io_services 就不会停止运行。话虽如此,既然线程与 io_service 相关联,我想知道为什么 io_service 首先会停止运行:毕竟,线程“链接”到 io_service 并继续自行运行;这显然与我一开始显然不明白这个线程在做什么的事实有关。

当我将“saysomething”方法添加到锅中时,事情变得更加复杂:我希望能够编写一些东西并打印该字符串,同时 2 个计时器继续工作。我使用的代码如下:

int main()
{
  boost::asio::io_service io;
  printer p(io);
  boost::thread t(&saysomething);
  io.run();
  std::cout << "Hey there\n";
  t.join();

  return 0;
}

结果如下:

Timer 1: 0
Timer 2: 1
Timer 1: 2
Timer 2: 3
Timer 1: 4
Timer 2: 5
Timer 1: 6
Timer 2: 7
ghg       //<--- my input
You said ghg
Timer 1: 8
Timer 2: 9
Hey there
Final count is 10

它工作得很好,但是现在没有与 io_service 关联的线程,它最初的目的是什么?

总结一下我的3个问题是:

标签: c++multithreadingboostboost-asio

解决方案


  • 为什么没有立即打印“Hey there”字符串而不是等待 io_service 停止运行?

main的线程io_service在打印之前也会阻塞,所以“嘿,那里”在服务停止之前不会打印。

  • 如果一个线程链接到io_service,它究竟是如何停止运行的,这应该相当于io_service有工作要做?

线程不是保持io_service活力的东西,计时器任务是。这io_service实际上是让线程在这里保持活力的那个。服务的工作是等待计时器,所以在计时器到期之前,服务还有工作要做。

  • 由于线程不允许“代码流”向前移动,并且将所述线程链接到我的方法而不是 io_service 不会导致任何错误,那么该线程首先的目的是什么?

从线程调用的目的run是将调用线程捐赠给io_service. 在run退出之前,服务拥有该线程,并且该线程是服务线程池的一部分。您发布到服务的任何任务都可以在服务池中时交给该线程。当您添加第二个线程时,第二个线程根本没有与服务交互,因为它没有调用run. 因此,它不是服务线程池的一部分。


推荐阅读