2013-05-06 42 views
7

读取boost :: asio的文档时,我仍然不清楚何时需要使用asio :: strand。假设我有一个线程使用io_service,那么它是安全的写在一个套接字如下?什么时候我必须使用boost :: asio:strand

void Connection::write(boost::shared_ptr<string> msg) 
{ 
    _io_service.post(boost::bind(&Connection::_do_write,this,msg)); 
} 

void Connection::_do_write(boost::shared_ptr<string> msg) 
{ 
    if(_write_in_progress) 
    { 
     _msg_queue.push_back(msg); 
    } 
    else 
    { 
     _write_in_progress=true; 
     boost::asio::async_write(_socket, boost::asio::buffer(*(msg.get())), 
     boost::bind(&Connection::_handle_write,this, 
      boost::asio::placeholders::error)); 
    } 
} 

void Connection::_handle_write(boost::system::error_code const &error) 
{ 
    if(!error) 
    { 
    if(!_msg_queue.empty()) 
    { 
      boost::shared_ptr<string> msg=_msg_queue.front(); 
     _msg_queue.pop_front(); 
     boost::asio::async_write(_socket, boost::asio::buffer(*(msg.get())), 
      boost::bind(&Connection::_handle_write,this, 
        boost::asio::placeholders::error)); 
     } 
    else 
    { 
     _write_in_progress=false; 
    } 
    } 
} 

多线程调用Connection :: write(..)或者我必须使用asio :: strand吗?

回答

17

简答:不,您不必在这种情况下使用strand

大致简化后,io_service包含一个函数对象(处理程序)的列表。在服务上调用post()时,处理程序将放入列表中。例如每当异步操作完成时,处理程序及其参数都将放入列表中。 io_service::run()执行一个接着一个的处理程序。因此,如果只有一个线程调用run()就像您的情况一样,则不会出现同步问题,也不需要strand
只有在多个线程在同一个io_service上调用run()时,才会同时执行多个处理程序,在N个线程中最多有N个并发处理程序。如果这是一个问题,例如如果在访问同一对象的同一时间队列中可能有两个处理程序,则需要strand
您可以将strand看作是一组处理程序的锁。如果线程执行与strand关联的处理程序,那么strand会被锁定,并在处理程序完成后被释放。任何其他线程只能执行不与锁定的strand关联的处理程序。

注意:这个解释可能过于简化和技术上不准确的,但它给在io_servicestrand S的会发生什么的一个基本概念。

2

仅从一个线程调用io_service::run()将导致所有事件处理程序在线程内执行,无论有多少个线程正在调用Connection::write(...)。因此,不可能同时执行处理程序,这是安全的。该文件将此称为implicit strand

另一方面,如果多个线程正在调用io_service::run(),那么将会需要一个链。 This答案涵盖更详细的股。

相关问题