我正在编写一个多线程套接字服务器,我需要确定。
关于线程的文章说我应该等待线程返回,而不是杀死它。但在某些情况下,我想要踢/禁用的用户线程将无法正常返回(例如,我开始发送大块数据并且send()此时阻止线程)所以我会只需杀死它。
为什么杀死线程函数很危险,什么时候会崩溃整个应用程序?
答案 0 :(得分:17)
杀死一个线程意味着完全停止所有执行。特别是,它不会执行任何析构函数。这意味着不会关闭套接字和文件,不会释放动态分配的内存,也不会释放互斥锁和信号量等。几乎可以保证杀死线程会导致资源泄漏和死锁。
因此,你的问题有点逆转。真正的问题应该是:
当可以在什么条件下我杀了一个帖子?
所以,当你确信没有泄漏和死锁时,你可以杀死线程,而不是现在,而不是当其他线程的代码被修改时(因此,几乎不可能保证)。
在您的特定情况下,解决方案是使用非阻塞套接字,并在调用send()
和recv()
之间检查一些线程/用户特定标记。这可能会使您的代码变得复杂,这可能是您拒绝这样做的原因,但这是正确的方法。
此外,您很快就会意识到每个客户端的线程无法扩展,因此您将改变您的架构并重新编写大量的架构。
答案 1 :(得分:7)
杀死一个线程可能会导致程序泄漏资源,因为该线程没有机会自行清理。考虑关闭线程发送的套接字句柄。这将导致阻塞send()立即返回适当的错误代码。然后线程可以清理并平静地死去。
答案 2 :(得分:4)
如果你以一种困难的方式杀死你的线程,它就会泄漏资源。
您可以在设计线程以支持取消时避免使用它。
请勿使用阻止调用或使用超时阻塞调用。以较小的块或异步方式接收或发送数据。
答案 3 :(得分:2)
有很多原因,但这里很简单:只有一个堆。如果一个线程在堆上分配了ANYTHING,并且你将其终止,那么它所分配的任何内容都会一直存在,直到进程结束。每个线程都有自己的堆栈,因此可以释放(依赖于实现),但是GUARANTEE不会让它自行关闭而在堆上泄漏。
答案 4 :(得分:2)
如果线程在I / O中被阻塞,你永远不需要杀死它,而是可以选择非阻塞I / O,超时和从另一个线程关闭套接字。其中任何一个都会解锁线程。
答案 5 :(得分:2)
你真的不想这样做。
如果你在一个关键部分杀死一个线程,它就不会被释放,这可能会导致你的整个应用程序崩溃。某些C库调用(如堆内存分配)使用关键部分,如果您在执行“new”时碰巧杀死了线程,那么从程序中的任何其他地方调用new将导致该线程停止。
你只是不能安全地做到这一点而没有真正的极端措施,这些措施比简单地通知线程终止自己更具限制性。