【问题标题】:[boost.asio]closing tcp::socket or tcp::acceptor in different thread from the I/O thread[boost.asio]在与 I/O 线程不同的线程中关闭 tcp::socket 或 tcp::acceptor
【发布时间】:2012-03-22 17:08:56
【问题描述】:

我可以在与同步读取线程不同的线程中关闭 tcp::socket 吗? 它看起来像:

boost::asio::ip::tcp::socket* tcp_socket;  //blocking mode

线程1:

while(true){
   try{
       std::vector<char> read_buffer(10);
       tcp_socket->read_some( boost::asio::buffer( read_buffer ) );
  }
  catch(boost::system::system_error& e){
  //TODO
  break;
  }
}

线程2:

tcp_socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both);
tcp_socket->close();

我看到了 tcp::socket 的document。他们说该对象是线程不安全的。但演示代码似乎运行良好。 那么安全吗?那么 tcp::acceptor 呢?我可以在多线程中调用关闭并接受吗 在同一个 tcp::acceptor 上?

【问题讨论】:

    标签: c++ boost boost-asio


    【解决方案1】:

    文档指出tcp::socket 对于共享对象不是线程安全的。

    不要指望它看起来可以保证它永远有效。

    此外,在套接字层从另一个线程关闭套接字并不是让阻塞线程解除阻塞的可移植方式。

    以下是我的建议:

    • 为 asio 使用异步 API。
    • 使用互斥锁保护套接字以防止并发访问或使用 asio 链序列化对其的访问。

    similar 问题上引用作者的话:

    其实……

    实际上,它可能会在目前的平台 asio 上运行 支持**。但是,我特意指定了这样的接口 它是线程安全的。这是为了允许实现 在套接字对象中存储额外的状态而不需要显式 同步。

    如果你想在同一个套接字上运行多个并发操作, 安全、可移植的方式是使用异步操作。

    **除非您使套接字非阻塞。

    干杯,克里斯

    【讨论】:

      【解决方案2】:

      这是安全的,只要你能保证关闭后没有其他线程在使用tcp_socket。对于您的示例,如果 thread2 尝试关闭线程时 thread1 仍处于读取循环中,您将遇到竞争条件。

      您可以使用thread-shared variables 通知thread1 退出循环,并使用a barrier 确保只有在thread1 处于安全状态后才关闭套接字。

      【讨论】:

      • 感谢您的回复。我运行我的演示代码。没有锁来同步 thread1 和 thread2。在调用 tcp_socket->close() 后,thread1 捕获“文件结束”异常,然后中断。我没有找到任何文件给出合理的解释。
      • 没有锁,任何事情都可能发生。您可能只是在您的平台上走运了,但这并不意味着它是可移植的。正如另一个答案所强调的那样:任何 种并发访问(即两个线程同时访问同一个对象)会导致麻烦。只有在禁止并发访问的情况下,才能在线程之间共享对象。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-15
      相关资源
      最近更新 更多