2010-08-20 113 views
6

我有一个等待条件变量的pthread使用pthread_cond_wait。它正在等待由另一个线程填充的队列结构中的数据。我想杀死这个线程,最好不用pthread_kill。在Linux和WinPthreads上执行pthread_cancel(); pthread_join()足以杀死它。但是,在OS X上它挂在pthread_join调用上。有什么建议么?杀死等待条件变量的pthread

+0

我使用SDL或许这是混杂的问题。我知道SDL提供了它自己的线程实现,也许我应该使用它,因为pthread/SDL有一些奇怪的交互,但我已经写了很多pthread代码,我宁愿保留它。 – CarbonAsh 2010-08-20 19:53:43

回答

6

你有排队的项目进入队列,并控制对象模式吗?如果是这样,请定义一个队列对象类型,当其排队时,指示正在处理该项目的线程正常退出。

现在,关闭这些线程,只是发布了一些这些“跳槽”的对象是对应于正在维修的队列中的线程数量的队列HEAD的,和加入的线程。

这似乎比pthread_cancel可以/杀的“核选项”干净多了。

+0

这其实就是我所做的!感谢您的建议,这样我的线程仍然可以保持在黑暗中,并在非线程实例中运行,并且我已经线程感知的队列可以处理肮脏的工作并调用pthread_exit来终止线程。 – CarbonAsh 2010-08-27 06:05:57

0

我会尝试的第一件事情是在cancel和join之间踢入condition变量,并让你的目标线程在从wait状态返回后明确地检查cancel消息。

这是因为它可能是线程在条件等待(或根本没有)时没有响应取消。

POSIX.1c-2004(V6)规定:

的可取消性状态和类型的任何新创建线程,包括线程,其中主()已首先被调用,应分别为PTHREAD_CANCEL_ENABLEPTHREAD_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()。我非常相信让线程控制自己的生命周期,因为我发现它总是会导致更少的并发问题。

旁白:事实上,已经收购了在并行线程的非常早的版本,甚至融入DCE之前,我还是发现自己只使用一个全局变量为每个线程指示何时应该退出,以及手动踢互斥或条件变量来唤醒线程。我想我应该更新我的方法(或者,如果我能看到明显的优势)。 :-)

+0

那么,我肯定会喜欢有一些不取消的方法,但我有,但获取取消的线程并不知道它在一个线程中运行。 我试过发信号通知条件变量,但是它从队列和段错误中读取,因为它里面什么也没有。虽然这具有退出程序的理想行为,但它似乎“只是错误的”。 – CarbonAsh 2010-08-20 19:26:54

+0

顺便说一句,你永远不应该认为,仅仅因为你从cond_wait返回,就有可用的工作。有两个线程可能会被唤醒,第一个获得工作,第二个线程应该检测到没有可用的工作,然后再等待。 – paxdiablo 2010-08-20 22:55:44

+1

延迟取消状态并不意味着你必须用'pthread_testcancel()'明确检查取消。这个功能只是POSIX定义的许多取消点之一。你几乎不会*想要异步取消,除非用* no *库进行任何长时间的数字计算。在启用异步取消时,唯一的库调用可以禁用异步取消。 :-) – 2010-12-21 06:11:43

6

pthread_cancel应该唤醒被阻止在pthread_cond_wait线程---这是需要取消点之一。如果它不起作用,那么有些事情是错误的。

首先要检查的是在目标线程上确实启用了取消功能---在目标线程上显式调用pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,&oldstate)以确保。如果这不起作用,那么平台上的取消操作就会中断,您将不得不采取其他方式,例如设置“请立即停止”标志并发送条件变量。

不要使用异步取消,除非你真的知道你在做什么---它可以触发取消任何操作过程中(例如,在设置函数调用堆栈帧或运行析构函数的过程中),因此可能会使代码处于完全不一致的状态。编写异步取消安全代码是hard

顺便提及pthread_kill确实不是杀死一个线程---它发送一个信号给它。

+0

我做了pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,&oldstate)。旧状态是PTHREAD_CANCEL_ENABLE,这没有效果。如果Mac OS X的pthreads被破坏,我会感到非常惊讶,但我不确定还有什么可能是错误的,因为此代码可以在Windows和Linux上运行。 – CarbonAsh 2010-08-20 19:40:34

+0

pthreads工作正常,我写了一个小程序: pthread_cond_t cond; pthread_mutex_t lock; 无效* tmain(无效*) { 的pthread_mutex_lock(&lock); 调用pthread_cond_wait(COND,&lock); 调用pthread_mutex_unlock(&lock); } INT主() { 的pthread_t螺纹; pthread_cond_init(COND,NULL); 调用pthread_mutex_init( &锁,NULL); 在pthread_create(&螺纹,NULL,tmain,NULL); 睡眠(1); pthread_cancel可以(线程); 在pthread_join(线程,NULL); } 要测试它,并在一秒钟后退出。我的代码中必须有一些其他的错误。 – CarbonAsh 2010-08-20 19:48:09