我最近在一个uni项目工作,我需要管理一对线程池。
池中的工作线程执行的操作基本上是对每个相应的队列执行某种弹出操作,如果队列中没有可用值,最后等待条件变量(pthread_cond_t
),并且一旦获得项目,解析它并相应地执行操作。
我关心的是我想要没有内存泄漏的事实,为了实现这一点,我注意到当主进程退出时在每个线程上调用pthread_cancel
绝对是一个坏主意,因为它离开了周围有很多垃圾。
关键是,我的第一个想法是使用退出标志,我可以在线程需要退出时设置,以便他们可以轻松释放内存并调用pthread_exit
...
我想我应该设置这个标志,然后向等待条件变量的线程发送广播信号,并在弹出操作后立即检查标志......
这真的是实现良好线程池终止的正确方法吗?我对此感到不自信...... 我在这里写一些伪代码来解释我在说什么
每个池线程都会运行一些如下结构的代码:
/* Worker thread (which will run on each pool thread) */
{ /* Thread initialization */ ... }
loop {
value = pop();
{ /* Mutex lock because of the shared flag */ ... }
if (flag) {{ /* Free memory and unlock mutex */ ... } pthread_exit(); }
{ /* Unlock the mutex */ ... }
{ /* Elaborate value */ ... }
}
return NULL;
并且会有某种pool_stopRunning()
函数看起来像:
/* pool_stopRunning() function code */
{ /* Acquire flag mutex */ ... }
setFlag(flag);
{ /* Unlock flag mutex */ ... }
{ /* Acquire queue mutex */ ... }
pthread_cond_broadcast(...);
{ /* Unlock queue mutex */ ... }
在此先感谢,我只需要确保没有一种花哨的方式来阻止线程池...(或者通过任何机会了解更好的方法) 和往常一样,如果有任何拼写错误,我很抱歉,我不是和说英语的人,现在已经很晚了>:
答案 0 :(得分:0)
关于设置标志和减少序列化的对称性,此代码:
{ /* Mutex lock because of the shared flag */ ... }
if (flag) {{ /* Free memory and unlock mutex */ ... } pthread_exit(); }
{ /* Unlock the mutex */ ... }
应如下所示:
{ /* Mutex lock because of the shared flag */ ... }
flagcopy = readFlag();
{ /* Unlock the mutex */ ... }
if (flagcopy) {{ /* Free memory ... } pthread_exit(); }
话虽如此,您可以(应该?)将互斥代码纳入setFlag和readFlag方法。
还有一件事。如果该标志只是一个布尔值,并且只在整个事件关闭之前改变了一次(即,它在设置后从未取消设置),那么我认为不需要用互斥锁来保护读取。 / p>
我之所以这样说是因为如果上述假设为真,并且循环的持续时间非常短并且循环迭代频率很高,那么您将对业务施加过度的序列化任务并可能无法接受地增加响应时间。
答案 1 :(得分:0)
你所描述的内容会起作用,但我建议采用不同的方法......
您已经有了一种为线程分配任务的机制,并完成了所有适当的同步。因此,不要使用一些新的并行机制使设计复杂化,只需定义一种称为“STOP”的新类型的任务。如果有N
个线程为队列提供服务而您想终止它们,请将N
个STOP任务推送到队列中。然后等待所有线程终止。 (最后这个可以通过“join”来完成,所以它也不需要任何新的机制。)
没有麻烦,没有大惊小怪。