我有一个使用pthread_cond_wait()
等待条件变量的pthread。它正在等待来自另一个线程填充的队列结构的数据。我想杀死这个帖子,最好没有pthread_kill()
。
在Linux和WinPthreads上做一个
pthread_cancel();
pthread_join()
足以杀死它。
但是,在OS X上它挂在pthread_join()
调用上。有什么建议?
您是否可以访问队列,并控制入队项目的对象架构?如果是这样,请定义一个队列对象类型,在排队时指示正在处理项目的线程正常退出。
现在,要关闭这些线程,只需将一些这些“退出”对象发布到队列的HEAD,该HEAD对应于为队列提供服务的线程数,并加入线程。
这似乎比pthread_cancel / kill的“核选项”更清晰。
pthread_cancel
应该唤醒在pthread_cond_wait
被阻止的线程---这是必需的取消点之一。如果它不起作用则出现问题。
要检查的第一件事是确实在目标线程上启用了取消---显式调用目标线程上的pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,&oldstate)
以确保。如果这不起作用,那么您的平台上的取消就会被取消,您将不得不采取其他方法,例如设置“请立即停止”标志并发出条件变量信号。
除非你真的知道你在做什么,否则不要使用异步取消 - 它可以在任何操作的中间触发取消(例如在设置函数调用堆栈帧或运行析构函数的过程中),因此可以离开您的代码处于完全不一致的状态。编写异步取消安全代码很难。
顺便说一句,pthread_kill
没有杀死一个线程---它向它发送一个信号。
我要尝试的第一件事就是在取消和连接之间启动条件变量,让目标线程在从条件等待返回后显式检查取消。
那是因为线程在条件等待(或根本没有)的情况下可能没有响应取消。
POSIX.1c-2004(v6)规定:
任何新创建的线程的可取消状态和类型,包括首次调用main()的线程,应分别为
PTHREAD_CANCEL_ENABLE
和PTHREAD_CANCEL_DEFERRED
。
这意味着您必须使用pthread_testcancel()
明确检查取消。
另一种选择是在第一次开始运行时将线程取消类型设置为PTHREAD_CANCEL_ASYNCHRONOUS
,例如:
int junk;
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &junk);
std::cout
<< ((junk==PTHREAD_CANCEL_DEFERRED) ? "Was deferred" : "Wasn't")
<< std::endl;
当然,这就是假设问题所在。你应该能够通过检查上面第三行的输出来测试它是否是。
取消是对目标线程的请求,如果它愿意,它可以自由地忽略,而不是更邪恶的pthread_kill()
。我非常相信让线程控制自己的生命,因为我发现它总是导致更少的并发问题。
旁白:事实上,在早期版本的pthreads中购买,甚至在集成到DCE之前,我仍然发现自己只是为每个线程使用一个全局变量来指示何时应该退出,同时手动踢互斥或条件变量来唤醒线程了。我想我应该更新我的方法(或者如果我能看到明显的优势,我会这样做)。 :-)