asio多线程环境 io_service和strand搭配使用
一个io_service对象可以通过多个线程调用io_service.run进行事件处理器的并发。分发到不同的线程上执行的策略可以认为是随机的。
strand是线程安全的任务队列的封装,具体执行还是会调用io_service的接口进行处理。一个io_service可以被多个strand绑定。
因此strand的特性是保证同一个strand里面的任务是按序执行,任务执行的线程是根据io_server.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; }
输出:
使用例子中的step1是直接使用io_service进行任务分发,因此执行顺序是乱序的。
使用例子中的step2是通过strand封装进行任务分发,因此是顺序执行,执行的线程也不一定是同一个。