C++ [boost.asio]在与I/O线程不同的线程中关闭tcp::socket或tcp::acceptor

C++ [boost.asio]在与I/O线程不同的线程中关闭tcp::socket或tcp::acceptor,c++,boost,boost-asio,C++,Boost,Boost Asio,我可以在同步读取线程的不同线程中关闭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 ) ); }

我可以在同步读取线程的不同线程中关闭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;
  }
}
我看到了tcp::socket的特性。他们说这个对象是线程不安全的,但是演示代码似乎工作得很好。 那么它安全吗?那么tcp::acceptor呢?我可以在多线程中调用close和accept吗
在同一个tcp::acceptor上

这是安全的,只要您能保证关闭后没有其他线程使用
tcp\u套接字
。例如,如果thread1在thread2尝试关闭线程时仍处于读取循环中,则会出现争用条件


您可以使用来通知thread1退出循环,并使用来确保仅在thread1处于安全状态后才关闭套接字。

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

不要指望它看起来能起作用,因为它能保证永远起作用

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

以下是我的建议:

  • 使用asio的异步API
  • 使用互斥锁保护套接字以防止并发访问,或使用asio串序列化对其的访问
在一个问题上引用作者的话:

实际上

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

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

**除非你让插座不阻塞

干杯,克里斯


谢谢你的答复。我运行了我的演示代码。没有同步thread1和thread2的锁。调用tcp_socket->close()后,thread1捕捉到“文件结束”异常并中断。我发现没有文档对此进行合理解释。没有锁,任何事情都可能发生。你可能在你的平台上很幸运,但这并不意味着它是便携式的。正如另一个答案强调的那样:任何类型的并发访问(即两个线程同时访问同一个对象)都会导致麻烦。只有在禁止并发访问的情况下,在线程之间共享对象才是安全的。
tcp_socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both);
tcp_socket->close();