我是一名 C++ 开发人员,主要在 Solaris 和 Linux 上进行编程,直到最近我被迫创建一个针对 Windows 的应用程序。
我一直在使用基于 TCP 套接字支持的 C++ I/O 流的通信设计。该设计基于单个线程连续从流中读取(大部分时间阻塞在套接字读取等待数据中),而其他线程通过同一流发送(通过互斥体同步)。
当迁移到 Windows 时,我选择使用 boost::asio::ip::tcp::iostream 来实现套接字流。我沮丧地发现上述多线程设计在Windows上导致了死锁。看来operator<<(std::basic_ostream<...>,std::basic_string<...>)
声明一个“Sentry”,它锁定输入和输出操作的整个流。由于我的读取线程始终在流上等待,因此在创建此 Sentry 时,其他线程的发送操作会死锁。
以下是operator
...
ntdll.dll!7c901046()
CAF.exe!_Mtxlock(_RTL_CRITICAL_SECTION * _Mtx=0x00397ad0) Line 45 C
CAF.exe!std::_Mutex::_Lock() Line 24 + 0xb bytes C++
CAF.exe!std::basic_streambuf<char,std::char_traits<char> >::_Lock() Line 174 C++
CAF.exe!std::basic_ostream<char,std::char_traits<char> >::_Sentry_base::_Sentry_base(std::basic_ostream<char,std::char_traits<char> > & _Ostr={...}) Line 78 C++
CAF.exe!std::basic_ostream<char,std::char_traits<char> >::sentry::sentry(std::basic_ostream<char,std::char_traits<char> > & _Ostr={...}) Line 95 + 0x4e bytes C++
> CAF.exe!std::operator<<<char,std::char_traits<char>,std::allocator<char> >(std::basic_ostream<char,std::char_traits<char> > & _Ostr={...}, const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & _Str="###") Line 549 + 0xc bytes C++
...
如果 istream 和 ostream 组件单独锁定,我会很好,但事实并非如此。
我可以使用流运算符的替代实现吗?我可以指示它不锁定吗?我应该实现自己的(不知道如何做到这一点)?
任何建议,将不胜感激。
(平台为 Windows 32 位和 64 位。使用 Visual Studio 2003 Pro 和 2008 Express 观察到的行为)