线程终止的两种方式及注意事项

感觉介绍很全的一篇文章,可以详细看一下,我主要写一下我在工作中遇到的问题   ——> 关于终止线程的文章

 

1.问题背景: 

在线程中进行图像处理,而处理函数出现不可控的死循环情况,概率很低,当前没有什么好的解决办法,使用取消线程,然后再重新启动的方式,强使运行正常。

2.线程的取消函数pthread_cancel 

int pthread_cancel(pthread_t thread);

函数很简单,将终止的线程的thread赋值给pthread_cancel函数即可,但是还要进行准备工作。

pthread_cancel函数是在除线程本身之外的线程中使用的,或者主线程。但是如果想要对指定线程进行cancel处理的话,那么此线程必须要进行配置准备。

举个栗子:

void *thread_function(void *arg)

{

  while(1){
    //dosomework...
    }

}

这是一个简单的线程,这样的线程是不对pthread_cancel 函数进行处理的,必须要在此线程里面进行配置才可以 

 

void *thread_function(void *arg)

{
 phread_setcancelstate(PTHREAD_CANCEL_ENABLE ,NULL);//设置使能为PTHREAD_CANCEL_ENABLE 
 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS , NULL); //设置取消类型
    while(1){
    //dosomework...
    }

}

设置本线程对pthread_cancel函数的配置函数有两个,一个是

int phread_setcancelstate(int state,int *oldstate);设置本线程对信号的反应

另一个是

int pthread_setcanceltype(int type, int *oldtype); 
PTHREAD_CANCEL_ASYNCHRONOUS 立即执行取消信号 
PTHREAD_CANCEL_DEFERRED 运行到下一个取消点 

我所遇到的问题,因为不知道具体的死循环的位置,所以设置取消点的方式是不适合的。只能使用第一种,立即返回的方式。

所以我当前的设置状态 PTHREAD_CANCEL_ASYNCHRONOUS 

对于立即返回的方式,重要的是对锁的解锁,还有对malloc资源的释放。还有就是,在PTHREAD_CANCEL_ASYNCHRONOUS 这种方式下,最好不要对线程使用

void pthread_cleanup_push(void (*routine) (void *), void *arg)

void pthread_cleanup_pop(int execute)

这种对资源的回收方式,容易出现断错误。因为线程结束的点不确定,所以结束时容易死机!!!

下面代码是我对pthread_cancel 的调用

if(pthread_cancel(thread)!=0)
{
    perror("cancel failed !");
}
if(pthread_join(thread)!=0)
{
    perror("pthread_join failed !");
}

phread_join()此处调用不知是否必要,反正是调用了是没问题的。。因为线程可能不会立即结束,所以我加了个join函数

 

第二种方式是设置取消点的方式,也是比较安全的取消方式,第一种方式不确定的点很多,可以说有很多坑的哇。

调用方式是类似的,不同的点就是在线程中设置的方式改为:PTHREAD_CANCEL_DEFERRED 

 

void *thread_function(void *arg)

{
 phread_setcancelstate(PTHREAD_CANCEL_ENABLE ,NULL);//设置使能为PTHREAD_CANCEL_ENABLE 
 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED  , NULL); //设置取消类型
    while(1){
    //dosomework...
    }

}

取消点: 
如果线程模式设置的是异步模式的话,那只有到取消点才会取消线程。下面会讲到两种取消方式。 
那取消点有哪些呢? 
1:通过pthread_testcancel 调用已编程方式建立线程取消点。 
2:线程等待pthread_cond_wait或pthread_cond_timewait中的特定条件。 
3:被sigwait(2)阻塞的函数。 
4:一些标准的库调用。通常这些调用包括线程可基于阻塞的函数。 
default情况下,会启用取消功能。 
POSIX标准中,pthread_join(), pthread_testcancel(), pthread_cond_wait(), pthread_cond_timewait(), sem_wait(), sigwait() 等函数以及read,write等会引起阻塞的系统调用。
如果没有默认取消点,那么可以是用pthread_testcancel()设置取消点。

void *thread_function(void *arg)

{
 phread_setcancelstate(PTHREAD_CANCEL_ENABLE ,NULL);//设置使能为PTHREAD_CANCEL_ENABLE 
 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED  , NULL); //设置取消类型
    while(1){
    pthread_testcancel();//此处设置为取消点,phthread_cancel调用后,执行到此处会结束线程
    //dosomework...
    }

}

很多比较基础的东西没有讲,相关的文章也很多。大家有问题可以和我交流。

 

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值