2013-05-06 45 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答案涵蓋更詳細的股。

相關問題