我使用Eclispse Indigo + CDT 8.0.2 + cygwin开发了一个多线程系统,代码如下:
pthread_mutex_t mutexCmd = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t signalCmd = PTHREAD_COND_INITIALIZER;
void * Func(void * arg)
{
int iStatus;
while (1)
{
int a = 1;
pthread_cleanup_push(pthread_mutex_unlock, &mutexCmd);
pthread_mutex_lock(&mutexCmd);
iStatus = pthread_cond_wait(&signalCmd, &mutexCmd);
if (iStatus) {
err_abort(iStatus, "signalCmd status error");
}
if(arg->Cmd != navi_Go) //Just a command tag;
{
pthread_mutex_unlock(&(pNaviCtrl->mutexCmd));
continue;
}
//do some work
//.....
pthread_mutex_unlock(&mutexCmd);
pthread_cleanup_pop(1);
}
//pthread_detach(pthread_self());
return NULL;
}
int main()
{
int iStatus = 0;
pthread = tid;
iStatus = pthread_create(&tid;NULL, Func, NULL);
if(iStatus)
{
err_abort(iStatus, "Start pthread error");
}
// do some work
...
//Cancel thread
void * retval;
iStatus = pthread_cancel(tid)
iStatus = pthread_join(tid; &retval);
if(iStatus){
err_abort(iStatus,"Stop thread error");
}
return iStatus;
}
在程序运行的地方,它停在“iStatus = pthread_join(tid1;& retval);”不能继续前进,我认为线程可能会陷入僵局,但找不到原因。我想在调用pthread_cancel()之后,线程将退出并返回到pthread_join(), 谁能告诉我我的代码有什么问题?
答案 0 :(得分:1)
pthread_cleanup_pop(1)
告诉pthread库不仅要从栈中弹出清理条目,还要执行它。所以这个电话也会隐含地调用:
pthread_mutex_unlock(&mutexCmd);
由于您已经解锁了互斥锁,因此该调用具有未定义的行为(假设互斥锁类型为PTHREAD_MUTEX_NORMAL
)。我想这个电话永远不会回来或什么的。
请注意,您的代码在处理清理时还有其他问题 - 如果您为循环执行continue
,则会再次调用pthread_cleanup_push()
(或更多),这将添加另一个清理上下文。
可能还有其他问题(我对pthread_cancel()
不太熟悉)。
答案 1 :(得分:1)
不要将cleanup_push和_pop放在while循环中。不要多次打电话给他们。如果你看一下它们,它们就是在{}中将代码包装在它们之间的宏。他们设置了一个在调用pthread_cancel时使用的longjump。