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