程序终止时清理 pthread 资源
Posted
技术标签:
【中文标题】程序终止时清理 pthread 资源【英文标题】:Clean up pthread resources when programme terminate 【发布时间】:2010-10-20 05:06:44 【问题描述】:我已经使用 pthread 创建了一个线程。我的工作程序是一个无限循环。当我的主程序退出时,终止和清理 pthread 的所有资源的设计模式是什么?
pthread_create(&thread, NULL, worker, NULL);
void* worker(void* arg)
while(true)
//do something
谢谢
【问题讨论】:
【参考方案1】:我通常有一个全局变量,当你希望线程退出并从主函数加入线程时,它被初始化为 true 并设置为 false。伪代码如下:
global isRunning = true
def main:
isRunning = true
id1 = startThread (worker)
id2 = startThread (worker)
id3 = startThread (worker)
joinThread (id1)
joinThread (id2)
joinThread (id3)
exit
def worker:
initialiseWorker()
while isRunning:
# something in here (or a signal handler) will
# set isRunning to false.
doSomeWork()
terminateWorker()
并确保线程及时执行该循环,以便它们能够检测到它们应该何时退出。如果他们有长时间运行的作业,您还需要在doSomeWork()
内定期检查。我制定了一条一般规则,即线程应在被告知后五秒内退出。
我从不从外部杀死线程。可以引入的问题太多了。全局标志方法让每个线程控制自己,因为它通常是唯一知道何时可以安全干净退出的线程。
【讨论】:
【参考方案2】:除了检查一个开关,全局的或其他的,pthreads 有它自己的取消机制。看看pthread_cancel()、pthread_setcancelstate()、pthread_setcanceltype()、pthread_testcancel()、pthread_cleanup_push()等
基本思想是工作线程创建(或使用现有的)取消点。如果取消,则在退出之前调用线程的推送清理处理程序以清理资源。
【讨论】:
【参考方案3】:当你的主程序退出时,所有线程也会退出。这意味着只有一个线程调用 exit()(或者如果主例程终止),那么其他线程将退出。
你不能仅仅杀死线程。如果你杀死正在工作的线程,那么最好的情况是你会发生内存泄漏,最坏的情况是你会遇到死锁。无论哪种方式,它都不漂亮。
在进程终止时清理的任何资源,将在最后一个线程退出时(或者如果任何线程调用 exit() )被清理。这包括内存(不包括共享内存,例如 posix 或 sysv)、类似文件的对象(如果没有其他进程具有打开的描述符)和一些其他类型的对象。
任何其他持久性(例如临时文件、某些类型的共享内存),您需要在退出之前或(更可靠地)在下一次运行开始时自行清理。
【讨论】:
【参考方案4】:所有线程都应该自行退出,否则您必须手动清理它们。在第一种方法中,您将不得不使用一些全局变量,这些变量将使用锁来保护,告诉线程停止执行。这样的事情将在每个线程的 while(true) 循环中。
while(true)
GetLock(SomeGlobalVariable);
if(SomeGlobalVariable == true)
unlock(SomeGlobalVariable);
break;
unlock(SomeGlobalVariable);
在第二种方法中,您必须跟踪您在数组中创建的所有 threadId,然后在退出时一一杀死所有这些 id。
如果您的程序要使用许多线程,那么您最好选择线程池。在线程池中,您在程序开始时创建一些线程,然后在需要时给线程,当工作完成时,线程资源被归还。
有这方面的库。例如http://threadpool.sourceforge.net/
【讨论】:
以上是关于程序终止时清理 pthread 资源的主要内容,如果未能解决你的问题,请参考以下文章
C语言 pthread_cleanup_push()和pthread_cleanup_pop()函数(用于临界资源程序段中发生终止动作后的资源清理任务,以免造成死锁,临界区资源一般上锁)