我的程序中有一个线程池(QueueWorkers
类),它们使用以下逻辑释放:
int QueueWorkers::stop()
{
for (unsigned int ix = 0; ix < threadIds.size(); ++ix)
{
pthread_cancel(threadIds[ix]);
pthread_join(threadIds[ix], NULL);
}
return 0;
}
其中threadIds
是类型为 的类变量std::vector<pthread_t>
。
这个逻辑在大多数情况下都有效,但我已经检查过它有一定概率失败的测试。特别是有时在下一行中pthread_cancel
的pthread_join
语句执行后永远不会返回并且我的程序挂起。
据我所知,到目前为止,pthread_join
在取消的线程上使用应该总是返回。是否有任何情况可以避免这种情况或以任何方式调试这里发生的事情?我在终止时释放线程的方法是否正确?
附加信息:线程有一个取消处理程序(使用 注册pthread_cleanup_push
),它释放线程使用的动态内存以避免泄漏。在正常情况下,处理程序被调用pthread_cancel
并且工作正常,但时间pthread_join
失败返回我检查过取消处理程序没有被调用。
提前致谢!
编辑:正如问题评论中所建议的,我修改了我的代码以检查pthread_cancel
. 无论之后是否pthread_join
按预期工作,它始终为 0 。
EDIT2:根据对此问题的一些评论的要求,让我提供有关其工作原理的更多详细信息。
线程池由以下start()
方法初始化:
int QueueWorkers::start()
{
// numberOfThreads and pQueue are class variables
for (int i = 0; i < numberOfThreads; ++i)
{
pthread_t tid;
pthread_create(&tid, NULL, workerFunc, pQueue);
threadIds.push_back(tid);
}
return 0;
}
启动函数workerFunc()
如下(简化):
static void* workerFunc(void* pQueue)
{
// Initialize some dynamic objects (Foo for simplification)
Foo* foo = initFoo();
// Set pthread_cancel handler
pthread_cleanup_push(workerFinishes, foo);
// Loop forever
for (;;)
{
// Wait for new item to process on pQueue
... paramsV = ((Queue*) pQueue)->pop();
// Then process it
...
}
// Next statemement never executes but compilation breaks without it. See this note in pthread.h:
// "pthread_cleanup_push and pthread_cleanup_pop are macros and must always be used in
// matching pairs at the same nesting level of braces".
pthread_cleanup_pop(0);
}
请注意pthread_cleanup_push()
启动以太网循环之前的语句。这样做是为了在取消Foo
对象时实现清理逻辑:
static void workerFinishes(void* curl)
{
freeFoo((Foo*) curl);
}
我希望没有过度简化代码。无论如何,您可以在此处查看原始版本。
确定线程处于取消状态还是您的线程cancelation_type
是异步的?
从man
的pthread_cancel
:
线程的取消类型由 pthread_setcanceltype(3) 确定,可以是异步的或延迟的(新线程的默认设置)。异步可取消性意味着线程可以随时取消(通常是立即取消,但系统不保证这一点)。延迟可取消性意味着取消将被延迟,直到线程下一次调用作为取消点的函数。pthreads(7) 中提供了是或可能是取消点的函数列表。
我不认为取消线程是确保线程完成的最佳方法。也许您可以向线程发送一条消息,它应该停止并确保线程确实收到消息并会处理它。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句