一个 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 封装分发任务,执行顺序有保证,但执行的线程不一定是同一个。