【问题标题】:Is it safe to call APIs of ASIO objects concurrently?并发调用 ASIO 对象的 API 是否安全?
【发布时间】:2020-03-30 19:37:05
【问题描述】:

我是 ASIO 的新手,想了解线程安全的工作原理,以便弄清楚在使用 ASIO API 时可以做出哪些假设。

到目前为止我发现了什么:

多个线程可以运行io_service.run()

因此,可能会调用 socket 等类中的处理程序 来自不同的线程,但只能来自执行io_service.run()的线程。

假设socket 有一些必须保护的内部状态 来自并发访问。

socket 将使用strand 包装其处理程序,这将执行序列化 的处理程序。它与在每个 处理程序,但性能更好。

但是socket也有公共方法,比如socket.async_write_some()。它 也可以从不同的线程调用。

假设socket.async_write_some() 访问相同的内部状态, 所以需要一些保护机制。

公共方法如何以安全的方式访问内部状态?

  • strand 可以用来序列化公共方法的调用吗?

  • 在公共方法中调用post([]{ /* actual implementation of the method goes here */})

  • 在链之外使用互斥锁?

在调用公共 API 时我可以做出哪些假设?

我可以假设socket 保护它的内部状态,即使我从不调用io_service.run() 的后台线程调用它?

如果是这样,是否有相关文档?我宁愿不依赖未记录的实现细节。

【问题讨论】:

  • 也就是说,你问asio怎么学,准确吗?无论如何看thatthat

标签: c++ boost-asio


【解决方案1】:

查看线程安全保证,这些保证与每个类一起记录,但通常也是https://www.boost.org/doc/libs/1_71_0/doc/html/boost_asio/overview/core/threads.html

这证实了:

问。我可以假设套接字保护它的内部状态,即使我从不调用 io_service.run() 的后台线程调用它?

不,你不能假设,因为它没有“保护它的内部状态”,你可能的意思是:它不会同步对它的访问。

此外,从运行io_service 处理程序的多线程 访问确实 意味着它是安全的。您可能需要strands(隐式或显式)来确保这一点。

【讨论】:

  • 我在 io_service 上使用了 c++11 thread_local 范围,对我来说效果很好。我假设拥有多个 io_service 对象是安全的。也许我应该使用股线......?
  • @moodboom io_service 是为数不多的被实际记录为可并发使用的线程安全的 Asio 对象之一。所以,不,拥有thread_local 没有多大意义(另外,这不是一个范围,而是一个生命周期或存储持续时间)。您可以拥有多个 io_services,但除非您在它们上 run() 或`poll(),否则它们不会做任何事情。
  • 是的,你是对的,我在抽烟,我不在 io_service 上使用 thread_local,抱歉。我确实有几个 io_service 对象,但只有一个主要对象,还有一些我临时使用的对象,例如进行出站 https 调用。现在我在想也许我应该与出站 https 通话共享一个。无论如何,我在 cmets 里太健谈了,抱歉。
猜你喜欢
  • 2020-10-03
  • 2011-01-28
  • 1970-01-01
  • 1970-01-01
  • 2018-07-10
  • 2016-12-23
  • 2017-02-17
  • 2017-04-21
  • 1970-01-01
相关资源
最近更新 更多