【问题标题】:Using Boost::Asio socket async and sync operations together一起使用 Boost::Asio 套接字异步和同步操作
【发布时间】:2016-03-05 13:04:50
【问题描述】:

我是 Boost C++ 新手,使用它来编写类似服务器的应用程序,我想知道是否可以同时使用 boost::asio::ip::tcp::socket::async_read_some(...)boost::asio::ip::tcp::socket::write_some(...)

在我的场景中,Connection 对象通过以下方式连续监听:

    void Connection::doRead()
{
    auto self(shared_from_this());
    socket_.async_read_some(boost::asio::buffer(data_rx_, max_length),
        [this, self](boost::system::error_code ec, std::size_t length)
        {
          if (!ec)
          {
              afterReading(length);
              doRead();
          }
        });
}

同时,异步函数回调(在不同的线程中运行)可以在 Connection 正在“读取”时调用 socket_.read_write

我阅读了各种 Boost::Asio 文档,但从未涉及过这种情况。

这是允许的吗?如果没有,应该怎么做才能避免?

编辑:

按照建议,我已经阅读了各种答案,包括:Why do I need strand per connection when using boost::asio?,但仍然找不到答案,因为未指定混合异步和同步(由不同线程调用)调用是否安全。

【问题讨论】:

  • 这个answer 可能会有所帮助。
  • @TannerSansbury 是对的,我认为这可能只是作为副本关闭。您需要使用 strands,而且在客户端没有在听,而是在忙着写的时候写信给客户端肯定没有任何意义。
  • 好吧,我阅读了答案,但找不到我的问题的答案。据说异步操作在从同一个线程启动时是线程安全的,而同步即使从 2 个不同的线程启动也可能是安全的(答案的注释 1)。没有提到混合异步和同步调用。所以我不认为这是重复的。

标签: c++ sockets boost boost-asio


【解决方案1】:

不安全。

这个answer 进行了详细介绍,但总而言之,多个线程同时进行调用是不安全的,除了例外多个同步调用可能如果操作系统支持,则安全。如果一个线程在一个socket上发起异步操作,而另一个线程在同一个socket上执行同步操作,则属于前一种情况,不安全。

最优雅的解决方案是避免混合同步和异步操作。

  • 如果使用同步操作并且操作系统不支持并发同步操作,则执行显式锁定,例如使用互斥锁。
  • 如果使用异步操作和多线程,则使用显式 strand 来防止并发调用处理程序。

此外,通过利用 Boost.Asio 对 futures 的支持,可以同步阻止等待异步操作完成。这种方法可以允许向用户公开同步阻塞 API,但在内部使用异步操作。启动操作 (async_*) 需要在链中调用,如果调用者不在链的上下文中运行,则需要使用某种形式的同步来允许调用者等待 Asio创建未来对象。

【讨论】:

  • "如果使用异步操作和多线程,则使用显式链来防止处理程序的并发调用。"此外,理论上,对启动函数 (async_) 的调用不应同时调用,因此您还应该同步调用,而不仅仅是处理程序的调用。尤其是在使用 ssl::stream 时。
猜你喜欢
  • 2011-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多