Boost asio asio串与数据同步
我发现asio关于通过Boost asio asio串与数据同步,boost-asio,Boost Asio,我发现asio关于通过strand进行同步的文档并不清楚。它只是说,在线程池设计asio应用程序中,处理程序可以在任何调用了io\u service::run()的线程中运行。使用串扭曲这些处理程序可以使它们的执行正确并发。在its中,所有的handle\u read都由strand包装,我认为Connection类中的变量,如buffer已经由strand同步,不同的线程调用handle\u read将获得最新数据,这是可以的。但是,连接类中定义了一个数据成员,这个数据成员也是由处理程序访问的
strand
进行同步的文档并不清楚。它只是说,在线程池设计asio应用程序中,处理程序可以在任何调用了io\u service::run()
的线程中运行。使用串
扭曲这些处理程序可以使它们的执行正确并发。在its中,所有的handle\u read
都由strand
包装,我认为Connection
类中的变量,如buffer
已经由strand
同步,不同的线程调用handle\u read
将获得最新数据,这是可以的。但是,连接
类中定义了一个数据成员,这个数据成员也是由处理程序访问的,而不是由串
包装的?我认为这是个问题,不是吗
在它的文档中,为什么
handle\u accept
没有被链
包裹?new\u connection\u
由多线程访问:new\u connection\u.reset
由线程A调用,而server::handle\u accept
由线程B调用。我想它需要在这里进行数据同步,否则线程B可能会使用一个过期的new\u connection\u
,而它的重置尚未调用。我想你不知何故,我们忽略了strand的含义。它不同步数据访问。它同步处理程序调用。这可以理解为“由给定的链包装的所有处理程序都不会被并发调用”
所以,您的第一个任务是:如果某个处理程序没有被strand包装,那么现在可以并发调用它。因此,它受到同步问题和/或RC的影响。注意,如果你在一个地方包装,并不意味着你是从钢筋混凝土保护;每次通话都应该这样做。因为strand不知道从其他线程调用什么,除非您使用.wrap
第二个问题:在给定的示例中,start\u accept设置接受处理程序handle\u accept,并且handle\u accept正在设置新的接受处理程序(通过调用start\u accept)。因此,它们不会被并发调用,因为您不能创建2个或更多的异步\u accept事件。当然,如果对同一个“服务器”实例执行其他线程调用start\u accept,则此示例可能会失败,但这样做显然是错误的。的设计方式实际上不需要串
Asio的一个基本特性是,对于给定的操作,处理程序最多只能调用一次。这种行为使得异步编程的调用路径更像是一个调用链
例如,检查图示的服务器的呼叫链
接受连接:
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\u accept
,是无关紧要的
connection::handle\u read
调用链和关于链的更多细节都有疑问。I根据我的经验,线程同步意味着数据和代码执行。缺少任何一个,同步将毫无意义。因为lock可以同时实现这两个功能。在这个示例中,如果串不进行数据同步,缓冲区数据成员将有问题。start_accept()和handle_accept()将在不同的线程中执行,因此为什么与数据成员“new_connection”的数据同步无关?start_accept()和handle_accept()不能同时执行。运行start\u accept
时,没有活动的async\u accept
,因此无法调用handle\u accept
。另一方面,当调用handle\u accept
时,io\u服务中不再有这样的处理程序;调用async\u accept()
时,它将添加到handle\u accept
的末尾。然而,有一个bug。由于new\u connection\u->start()
未保存new\u connection\u
shared\u ptr,它将在async\u accept
中重写。所以你是对的,这可能会失败,但在其他地方(在连接类中)。注意这是不完整的,我知道它们不会由不同的线程同时执行。我的问题是,当线程A在线程B完成start_accept()执行后调用句柄_accept()时,如何同步共享变量“new_connection”的状态。因为线程B调用'new_connection_uu'reset(),这将改变它的状态。在没有任何显式同步的情况下,线程A如何看到这些状态的变化?由于start\u accept()
被设计为只从对象外部启动一次,从对象内部启动多次,因此只有当handle\u accept
准备就绪时才会调用new\u connection\u.reset()
;而且是同一条线。如果某个线程在这个实例已经运行时调用了start\u accept()
,那么它就有麻烦了。但这样做是用户的错误。我得到两点:1,在asio中,处理程序调用链是并发的,正如文档所说的“隐式链”。2,HTTP示例3的句柄_read不需要包装在串中,因为它构成了一个链。我说得对吗?@jean:在图示的链中,有一个异步操作链与接受器
关联。因此,不可能并发执行与此链关联的处理程序。另一方面,这些处理程序可能与另一个链的处理程序同时运行,例如每个连接
的handle\u read
。是的,handle\u read
中的链
是不必要的,因为该链形成一个隐式链。