Strands:使用线程而无需显式锁定
Strand定义 Strand被定义为事件处理程序的严格顺序调用(即没有并发调用)。使用strands可以在多线程程序中执行代码,而无需显式锁定(例如,使用互斥锁)。
Strands可以是隐式或显式的,以下是几种替代方法的示例:
仅从一个线程调用io_context::run()意味着所有事件处理程序在隐式strand中执行,因为io_context保证处理程序仅在run()内部被调用。
当与连接关联的异步操作形成单一链(例如,在像HTTP这样的半双工协议实现中)时,处理程序之间不存在并发执行的可能性。这是一个隐式strand。
显式strand是strand<>或io_context::strand的实例。所有事件处理程序的函数对象需要使用boost::asio::bind_executor()绑定到strand,或者通过strand对象进行发布/调度。
在组合异步操作的情况下,如async_read()或async_read_until(),如果完成处理程序经过一个strand,则所有中间处理程序也应经过相同的strand。这是为了确保对调用者和组合操作之间共享对象的线程安全访问(在async_read()的情况下是套接字,调用者可以通过close()取消操作)。
为此,所有异步操作通过使用get_associated_executor函数获取处理程序的关联执行器。例如:
boost::asio::associated_executor_t<Handler> a = boost::asio::get_associated_executor(h);关联执行器必须满足执行器的要求。异步操作将使用它来提交中间和最终处理程序进行执行。
可以通过指定嵌套类型executor_type和成员函数get_executor()来自定义特定处理程序类型的执行器:
class my_handler
{
public:
// 自定义实现执行器类型要求。
typedef my_executor executor_type;
// 返回自定义执行器实现。
executor_type get_executor() const noexcept
{
return my_executor();
}
void operator()() { ... }
};在更复杂的情况下,可以直接部分特化associated_executor模板:
boost::asio::bind_executor()函数是一个助手,用于将特定的执行器对象(例如strand)绑定到完成处理程序。这种绑定自动关联一个执行器,如上所示。例如,要将strand绑定到完成处理程序,可以简单写为:
associated_executor, get_associated_executor, bind_executor, strand, io_context::strand, tutorial Timer.5, HTTP server 3 example.
Last updated