我发现asio关于strand
同步的文档很模糊。它只是说在线程池设计asio应用程序中,处理程序可以在任何调用io_service::run()
的线程中运行。使用strand
来扭曲这些处理程序可以使它们的执行正确并发。在example3中,所有handle_read
都由strand
换行,我认为Connection
类中的变量(例如buffer
)已由strand
同步},不同的线程调用handle_read
将获取最新数据,即可。但是,在Connection
类中定义的数据成员也可以由strand
包裹,它也由处理程序访问?我认为这是一个问题,不是吗?
在其文档example3中,为什么handle_accept
没有被strand
包裹?多线程访问new_connection_
:线程A调用new_connection_.reset
,线程B调用server::handle_accept
。我认为这需要数据同步,否则线程B可能会使用日期new_connection_
尚未调用其重置。
答案 0 :(得分:1)
我认为你在某种程度上忽略了 strand 的含义。 它不同步数据访问。它同步处理程序调用。这可以理解为“由给定的 strand 包裹的所有处理程序不会被同时调用”。
所以,你的第一个任务:如果某个处理程序没有被strand包裹 - 它现在可以同时调用。所以它的主题是同步问题和/或RC。请注意,如果您在一个地方包装并不意味着您受到RC的保护;这应该在每次通话中完成。除非你使用.wrap
第二个问题:在给定示例中 start_accept 设置接受处理程序 handle_accept , handle_accept 设置新的接受处理程序(通过调用 start_accept 强>)。因此,它们不会同时调用,因为您无法创建2个或更多 async_accept 事件。当然,如果其他线程为同一个“服务器”实例调用 start_accept - 这个例子可以/将会失败,但这样做是明显的错误。
答案 1 :(得分: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
运行的线程无关紧要。
在this问题中回答了connection::handle_read
个调用链以及有关股的更多详细信息。