一个 io_service 对象可以让多个线程同时调用 io_service.run,从而并发处理事件。任务被分发到哪个线程执行,策略上可以视为随机的。

strand 是对线程安全任务队列的封装,实际执行仍通过 io_service 的接口完成。一个 io_service 可以被多个 strand 绑定。

strand 的核心特性是:同一个 strand 内的任务保证按序执行,但执行任务的线程由 io_service.run 的线程池动态分配,因此同一个 strand 内不同任务的执行线程不一定是同一个。

strand.post 的实现

void strand_service::do_post(implementation_type& impl,
    operation* op, bool is_continuation)
{
  impl->mutex_.lock();
  if (impl->locked_)
  {
    // Some other handler already holds the strand lock. Enqueue for later.
    impl->waiting_queue_.push(op);
    impl->mutex_.unlock();
  }
  else
  {
    // The handler is acquiring the strand lock and so is responsible for
    // scheduling the strand.
    impl->locked_ = true;
    impl->mutex_.unlock();
    impl->ready_queue_.push(op);
    io_service_.post_immediate_completion(impl, is_continuation);
  }
}

使用示例

int main(int argc, char* argv[])
{
	io_service io;
	io_service::work worker(io);

	for (int i = 0; i < 3; i++)
	{
		std::thread t([&](){io.run(); });
		t.detach();
	}
	boost::asio::strand str1(io);

	// step 1
	for (int i = 0; i < 10; i++)
	{
		io.post([=]()
		{
			cout << i << endl;
		});
	}

	std::this_thread::sleep_for(std::chrono::seconds(1));
	cout << "AAAAAAAAAAAAAAAAAAAAA" << endl;

	// step 2
	for (int i = 0; i < 10; i++)
	{
		str1.post([=]()
		{
			cout << i << " tid:" << std::this_thread::get_id() << endl;
		});
	}

	::system("pause");
	return 0;
}

输出结果:

  • step 1:直接通过 io_service 分发任务,执行顺序是乱序的。
  • step 2:通过 strand 封装分发任务,执行顺序有保证,但执行的线程不一定是同一个。