我创建了一个在阻塞套接字上接收的线程,它等待数据包到达。但是,当我尝试断开主线程时,线程之间会出现导致错误的竞争条件。
此处切换发生在线程之间的第5行,而没有实际完成断开连接调用。
void Disconnect() {
if(isConnected) {
if (closesocket(sockClient) != SOCKET_ERROR) {
isConnected = false;
}
}
}
我应该如何避免交换机并优雅地让它完成断开连接呼叫?
答案 0 :(得分:1)
以下是两种可能的解决方案。
您可以在套接字(非主要)线程中隔离所有套接字访问,而不是从主线程断开套接字,让该线程发信号通知需要断开连接(或其他某些操作)的非主线程。这将要求您的辅助线程等待两个对象 - 套接字和信号器(Win32 Event,比如说),表明需要断开连接。
另一方面,如果您希望允许主线程断开(正如您现在所做),则需要检查使用该套接字的所有代码,并使用锁定保护程序使其成为线程安全的,以确保并发访问套接字和相关的状态数据被阻止。 Boost.Thread具有您可以在此处使用的合适锁,否则您可以将您自己的锁实现为Win32 CriticalSection之类的包装器。
第二个是我的首选解决方案 - 您提出这个问题意味着您需要回过头来考虑设计中的线程安全性。即使你按照上面的第一个想法,你仍然可能需要保持状态,以避免从主线程发送多个断开信号,并且必须锁定保护。此外,如果您希望非主线程处理除“disconnect”之外的传入事件,则必须在线程之间管理关联状态。
我认为您现在所处的阻力最小的路径是为现有代码添加锁定。确保尽可能窄地锁定锁定范围 - 例如,不要设置可以阻塞或花费很长时间的任何套接字调用的锁定。