C 如何从无限循环外部杀死无限循环中的pthread?
我创建了一个线程,并将其放入一个无限循环中。我在用valgrind检查代码时发现内存泄漏。这是我的密码:C 如何从无限循环外部杀死无限循环中的pthread?,c,memory-leaks,pthreads,threadpool,C,Memory Leaks,Pthreads,Threadpool,我创建了一个线程,并将其放入一个无限循环中。我在用valgrind检查代码时发现内存泄漏。这是我的密码: #include <pthread.h> #include <time.h> void thread_do(void){ while(1){} } int main(){ pthread_t th; pthread_create(&th, NULL, (void *)thread_do, NULL); sleep(2
#include <pthread.h>
#include <time.h>
void thread_do(void){
while(1){}
}
int main(){
pthread_t th;
pthread_create(&th, NULL, (void *)thread_do, NULL);
sleep(2);
/* I want to kill thread here */
sleep(2);
return 0;
}
#包括
#包括
无效线程(无效){
而(1){}
}
int main(){
pthread_t th;
pthread_create(&th,NULL,(void*)thread_do,NULL);
睡眠(2);
/*我想在这里杀线*/
睡眠(2);
返回0;
}
因此,在main中创建了一个线程,该线程一直运行thread_do()。有没有办法在2秒后从主干道内杀死它?我已经尝试了pthread\u detach(th)
和pthread\u cancel(th)
,但仍然出现漏洞。一些小想法:
线程\u do()
将永远不会被取消,因为它从不调用任何作为取消点的函数:线程的取消类型,由
pthread_setcanceltype(3)可以是异步的,也可以是
延迟(新线程的默认值)。异步的
可取消性意味着线程可以随时取消
时间(通常立即,但系统不保证
这个)。延迟取消意味着取消将
被延迟,直到线程下一次调用
取消点。是或可能是的函数列表
pthreads(7)中提供了取消点。
pthread\u join(3)
:在一个被取消的线程终止后
使用pthread_join(3)的线程将pthread_作为
线程的退出状态。(用螺纹连接是唯一的方法
要知道取消已完成。)
正如@sarnold指出的,默认情况下,如果不调用任何作为取消点的函数,就不能使用pthread\u cancel()
取消线程。。。但这可以通过使用pthread\u setcanceltype()
将线程的取消类型设置为异步而不是延迟来改变。为此,您需要添加类似于pthread\u setcanceltype(pthread\u CANCEL\u ASYNCHRONOUS,NULL)的内容代码>在线程函数的开始附近,在开始循环之前。然后,您可以通过从main()
调用pthread\u cancel(th)
来终止线程
但是请注意,以这种方式取消线程(无论异步与否)并不会清理线程函数中分配的任何资源(正如Kevin在评论中所指出的)。为了干净地执行此操作,您可以:
- 确保线程在退出前不执行任何需要清理的操作(例如,使用
malloc()
分配缓冲区)
- 确保在线程退出后,在其他地方的线程之后,您有一些清理方法
- 使用
pthread\u cleanup\u push()
和pthread\u cleanup\u pop()
添加清理处理程序,以便在取消线程时清理资源。请注意,如果取消类型是异步的,这仍然是有风险的,因为线程可能会在分配资源和添加清理处理程序之间被取消
- 避免使用
pthread\u cancel()
,让线程检查一些条件以确定何时终止(这将在长时间运行的循环中进行检查)。由于线程随后会检查终止本身,因此它可以在检查后执行所需的任何清理
实现最后一个选项的一种方法是使用互斥体作为标志,并使用封装在函数中的pthread\u mutex\u trylock()对其进行测试,以在循环测试中使用:
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
/* Returns 1 (true) if the mutex is unlocked, which is the
* thread's signal to terminate.
*/
int needQuit(pthread_mutex_t *mtx)
{
switch(pthread_mutex_trylock(mtx)) {
case 0: /* if we got the lock, unlock and return 1 (true) */
pthread_mutex_unlock(mtx);
return 1;
case EBUSY: /* return 0 (false) if the mutex was locked */
return 0;
}
return 1;
}
/* Thread function, containing a loop that's infinite except that it checks for
* termination with needQuit()
*/
void *thread_do(void *arg)
{
pthread_mutex_t *mx = arg;
while( !needQuit(mx) ) {}
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t th;
pthread_mutex_t mxq; /* mutex used as quit flag */
/* init and lock the mutex before creating the thread. As long as the
mutex stays locked, the thread should keep running. A pointer to the
mutex is passed as the argument to the thread function. */
pthread_mutex_init(&mxq,NULL);
pthread_mutex_lock(&mxq);
pthread_create(&th,NULL,thread_do,&mxq);
sleep(2);
/* unlock mxq to tell the thread to terminate, then join the thread */
pthread_mutex_unlock(&mxq);
pthread_join(th,NULL);
sleep(2);
return 0;
}
#包括
#包括
#包括
/*如果互斥锁已解锁,则返回1(true),这是
*线程的终止信号。
*/
int needQuit(pthread\u mutex\u t*mtx)
{
开关(pthread\u mutex\u trylock(mtx)){
案例0:/*如果我们得到锁,解锁并返回1(true)*/
pthread_mutex_unlock(mtx);
返回1;
case EBUSY:/*如果互斥锁被锁定,则返回0(false)*/
返回0;
}
返回1;
}
/*线程函数,包含一个无限循环,但它检查
*使用needQuit()终止
*/
void*thread\u do(void*arg)
{
pthread_mutex_t*mx=arg;
而(!needQuit(mx)){}
返回NULL;
}
int main(int argc,char*argv[])
{
pthread_t th;
pthread_mutex_t mxq;/*用作退出标志的互斥体*/
/*在创建线程之前初始化并锁定互斥锁
互斥锁保持锁定,线程应保持运行
互斥量作为参数传递给线程函数*/
pthread_mutex_init(&mxq,NULL);
pthread_mutex_lock(&mxq);
pthread_create(&th,NULL,thread_do,&mxq);
睡眠(2);
/*解锁mxq以通知线程终止,然后加入线程*/
pthread_mutex_unlock(&mxq);
pthread_join(th,NULL);
睡眠(2);
返回0;
}
如果线程未分离(默认情况下通常不分离),则应在停止线程后调用pthread\u join()
。如果线程被分离,您不需要加入它,但是您不知道它何时终止(或者大约终止,除非您添加另一种方式来指示它的退出)。取消pthreads意味着线程没有机会清理它分配的任何内存。好的,我通过使用一个全局keepalive=1
解决了这个问题。然后我将while(1)
更改为while(keepalive)
。现在要杀死线程,我只需将变量keepalive的值更改为0,瞧!要对多个pthread使用这个互斥解决方案,我需要每个线程一个互斥,对吗?在这种情况下,你会推荐这种解决方案吗?@RicardoCrudo不,只有一个互斥锁。。。如果needQuit()
成功锁定它,它会在。。。只有main()。有我们的线索吗