c++ - 了解多线程如何与 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个问题是:
- 为什么没有立即打印“Hey there”字符串而不是等待 io_service 停止运行?
- 如果一个线程链接到io_service,它究竟是如何停止运行的,这应该相当于io_service有工作要做?
- 由于线程不允许“代码流”向前移动,并且将所述线程链接到我的方法而不是 io_service 不会导致任何错误,那么该线程首先的目的是什么?
解决方案
- 为什么没有立即打印“Hey there”字符串而不是等待 io_service 停止运行?
main
的线程io_service
在打印之前也会阻塞,所以“嘿,那里”在服务停止之前不会打印。
- 如果一个线程链接到io_service,它究竟是如何停止运行的,这应该相当于io_service有工作要做?
线程不是保持io_service
活力的东西,计时器任务是。这io_service
实际上是让线程在这里保持活力的那个。服务的工作是等待计时器,所以在计时器到期之前,服务还有工作要做。
- 由于线程不允许“代码流”向前移动,并且将所述线程链接到我的方法而不是 io_service 不会导致任何错误,那么该线程首先的目的是什么?
从线程调用的目的run
是将调用线程捐赠给io_service
. 在run
退出之前,服务拥有该线程,并且该线程是服务线程池的一部分。您发布到服务的任何任务都可以在服务池中时交给该线程。当您添加第二个线程时,第二个线程根本没有与服务交互,因为它没有调用run
. 因此,它不是服务线程池的一部分。
推荐阅读
- c# - C# EmguCV 中 OpenCV 中的“getTickFrequency”等价物是什么?
- mysql - 如何在 group by 子句的一列中计算多个列和多个不同的值
- cpu-cache - Linux下获取cpu缓存放置策略的方法
- html - Search HTML elements for specific attribute values
- asp.net-mvc - Filezilla + hostgator transfer failed rosyln
- swift - Unmanaged Object and Protocol
- excel - 如何在 Scala/Spark 中创建包含来自多个 DataFrame 的多个工作表的 excel 文件?
- r - Pass dynamic column name to transform() R function
- javascript - Wait for asynchronous calls to complete and return
- ruby - 如何将我的液体脚本绑定到 HTML 文件?