【问题标题】:Understanding how multithreading works with Boost io_service了解多线程如何与 Boost io_service 一起工作
【发布时间】:2020-07-31 05:53:28
【问题描述】:

我正在学习多线程和 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 关联的线程,它最初的目的是什么?

总结我的三个问题是:

  • 为什么不立即打印“Hey there”字符串,而不是等待 io_service 停止运行?
  • 如果有线程链接到io_service,它究竟是如何停止运行的,这应该相当于io_service有工作要做?
  • 由于线程不允许“代码流”向前移动,并且将所述线程链接到我的方法而不是 io_service 并没有导致任何错误,那么该线程最初的目的是什么?

【问题讨论】:

    标签: c++ multithreading boost boost-asio


    【解决方案1】:
    • 为什么不立即打印“Hey there”字符串,而不是等待 io_service 停止运行?

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

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

    线程不是保持io_service 存活的原因,定时器任务才是。 io_service 实际上是在这里保持线程活跃的那个。服务的工作是等待计时器,所以在计时器到期之前,服务还有工作要做。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-17
      • 2011-12-18
      • 2012-05-18
      • 2017-12-31
      • 1970-01-01
      • 1970-01-01
      • 2016-01-07
      相关资源
      最近更新 更多