0

我发现 asio 关于同步的文档strand是晦涩难懂的。它只是说在线程池设计 asio 应用程序中,处理程序可以在任何具有 call 的线程中运行io_service::run()。使用 astrand扭曲这些处理程序可以使它们的执行正确并发。在它的example3中,所有handle_read的都是 wrap by strand,我认为Connection类中的变量,比如buffer已经同步过strand,不同的线程调用handle_read会得到最新的数据,没关系。但是如果在类中定义了Connection一个也被处理程序访问的数据成员没有被包装strand呢?我认为这是一个问题,不是吗?

在其文档example3中,为什么handle_accept不被 a 包裹strand?由new_connection_多线程访问:new_connection_.reset由线程Aserver::handle_accept调用并由线程B调用。我认为它需要在这里进行数据同步,否则线程B可能会使用new_connection_尚未调用其重置的过期。

4

2 回答 2

1

我认为您以某种方式错过了strand的含义。它不同步数据访问。它同步处理程序调用。这可以理解为“不会同时调用给定链包裹的所有处理程序”。

所以,你的第一个问题:如果某些处理程序没有被 strand 包裹 - 现在可以同时调用它。因此它会受到同步问题和/或 RC 的影响。请注意,如果您包裹在一个地方并不意味着您受到 RC 的保护;这应该在每次通话中完成。因为 strand 不知道你从其他线程调用什么,除非你使用.wrap

第二个问题:在给定的示例start_accept设置接受处理程序handle_accept,并且handle_accept正在设置新的接受处理程序(通过调用start_accept)。因此,它们不会被同时调用,因为您不能创建 2 个或更多async_accept事件。当然,如果其他线程为同一个“服务器”实例调用start_accept - 这个例子可能/将会失败,但这样做是一个明显的错误。

于 2013-02-08T10:04:54.933 回答
1

HTTP Server 3的设计方式使其实际上不需要strand.

Boost.Asio 的一个基本特征是,对于给定的操作,处理程序最多会被调用一次。这种行为允许将异步编程的调用路径更多地设想为调用链。

例如,检查server接受连接的图示调用链:

server::server(...)
{
  start_accept();  --.
}                    |
    .----------------'
    |      .----------------------------------------.
    V      V                                        |
void server::start_accept()                         |
{                                                   |
  new_connection_.reset(new connection(...));       |
  acceptor_.async_accept(..., handle_accept);  --.  |
}                                                |  |
    .--------------------------------------------'  |
    |                                               |
    V                                               |
void server::handle_accept(...)                     |
{                                                   |
  if (!error)                                       |
  {                                                 |
    new_connection_->start();                       |
  }                                                 |    
  start_accept();  ---------------------------------'
}

如图所示,仅存在一个异步事件链。由于不可能在 上同时执行处理程序或操作new_connection,因此据说它在隐式链中运行。处理程序运行的线程server::handle_accept无关紧要。

这个问题回答connection::handle_read调用链和有关股的更多详细信息。

于 2013-02-08T15:24:30.670 回答