posix多线程--线程取消
1.三种取消状态
Off 禁用取消
Deferred 推迟取消:在下一个取消点执行取消
Asynchronous 异步取消:可以随时执行取消
int pthread_cancel(pthread_t thread)
2.推迟取消:在下一个取消点执行取消
Pthreads系统上的某些函数会被作为取消点,如pthread_testcancel,sleep,pthread_cond_wait等。
线程调用pthread_cancel函数后,被取消线程不会立即取消,仅仅在到达取消点时响应取消请求。
代码示例如下:
在pthread_testcancel取消点,响应线程取消请求。
#include<stdio.h>
#include<pthread.h>
#include<errno.h>
int counter;
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
void *thread_route(void *arg)
{
pthread_mutex_lock(&mutex);
for(counter=;;counter++)
{
if(counter%==){
printf("calling testcancel\n");
pthread_testcancel();
} }
pthread_mutex_unlock(&mutex);
}
int main(void)
{
pthread_t tid;
void *result;
pthread_create(&tid,NULL,thread_route,NULL);
sleep();
printf("call cancel\n");
pthread_cancel(tid);
printf("call joining\n");
pthread_join(tid,&result);
if(result==PTHREAD_CANCELED)
{
printf("Thread cancelled at %d\n",counter);
}
else{
printf("Thread was not canceled\n");
}
pthread_mutex_lock(&mutex);
printf("main thread locked");
pthread_mutex_unlock(&mutex);
}
3.如果要保证取消不在一个特别的取消点发生,可以暂时在代码的那个区域停用取消。
int pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,int *state)
代码示例如下:
在sleep()时,禁用取消。
#include<stdio.h>
#include<pthread.h>
#include<errno.h>
int counter;
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
void *thread_route(void *arg)
{
int state;
pthread_mutex_lock(&mutex);
for(counter=;;counter++)
{
if(counter%==)
{
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,&state)
;
sleep();
pthread_setcancelstate(state,&state);
}
if(counter%==){
printf("calling testcancel\n");
pthread_testcancel();
} }
pthread_mutex_unlock(&mutex);
}
int main(void)
{
pthread_t tid;
void *result;
pthread_create(&tid,NULL,thread_route,NULL);
sleep();
printf("call cancel\n");
pthread_cancel(tid);
printf("call joining\n");
pthread_join(tid,&result);
if(result==PTHREAD_CANCELED)
{
printf("Thread cancelled at %d\n",counter);
}
else{
printf("Thread was not canceled\n");
}
pthread_mutex_lock(&mutex);
printf("main thread locked");
pthread_mutex_unlock(&mutex);
}
4.异步取消:可以随时执行取消
异步取消不需要使用取消点来查询取消请求。异步取消不能获得任何资源,应避免异步的取消
代码示例如下:
矩阵相乘线程取消
#include<stdio.h>
#include<pthread.h>
#define SIZE 10
int arr_a[SIZE][SIZE];
int arr_b[SIZE][SIZE];
int arr_c[SIZE][SIZE];
void printarr(int arr[SIZE][SIZE])
{
int i,j;
for(i=;i<SIZE;i++)
{
for(j=;j<SIZE;j++)
{
printf("%x ",arr[i][j]);
}
printf("\n");
}
}
void *thread_routine(void *arg)
{
int i,j,cancel_type;
for(i=;i<SIZE;i++)
for(j=;j<SIZE;j++)
{
arr_a[i][j] = i;
arr_b[i][j] = j;
}
while()
{
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,&cancel_type);
for(i=;i<SIZE;i++)
for(j=;j<SIZE;j++)
{
arr_c[i][j] = arr_a[i][j]*arr_b[i][j];
}
pthread_setcanceltype(cancel_type,&cancel_type);
for(i=;i<SIZE;i++)
for(j=;j<SIZE;j++)
arr_a[i][j] = arr_c[i][j];
}
}
int main(void)
{
pthread_t tid;
void *result;
pthread_create(&tid,NULL,thread_routine,NULL);
sleep();
printf("canceling!");
pthread_cancel(tid);
printf("joining");
pthread_join(tid,&result);
if(result==PTHREAD_CANCELED)
printf("thread cancelled\n");
else
printf("thread was not cancelled\n");
printarr(arr_a);
printarr(arr_b);
printarr(arr_c);
}
5.清除
在编写代码时,应将其设计为可以推迟取消,在不适当的地方停用取消,在取消点使用清除处理器。
清除处理器可以理解为每个线程有一个活动的清除处理函数的栈,调用pthread_cleanup_push将清除函数加到栈中,调用pthread_cleanup_pop删除最近增加的处理函数。当所有活动的清除处理函数返回时,线程被终止。当pthread_cleanup_pop以非零值被调用时,即使线程没被取消,清除处理函数也要被执行。
代码示例如下:
当一个条件变量等待被取消时,使用一个清除处理函数来释放互斥量。
#include<stdio.h>
#include<pthread.h>
#define THREADS 5
typedef struct work_tag
{
pthread_mutex_t mutex;
pthread_cond_t cond;
int counter;
int busy;
}work_t;
work_t work = {PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER,,};
void cleanup_handler(void *arg)
{
work_t *work_p = (work_t*)arg;
work_p->counter--;
pthread_mutex_unlock(&work_p->mutex);
}
void *thread_routine(void *arg)
{
pthread_cleanup_push(cleanup_handler,(void *)&work);
pthread_mutex_lock(&work.mutex);
work.counter++;
while(work.busy)
{
pthread_cond_wait(&work.cond,&work.mutex);
}
pthread_cleanup_pop();
return NULL;
}
int main(void)
{
pthread_t tid[THREADS];
void *result;
int i;
for(i=;i<THREADS;i++)
{
pthread_create(&tid[i],NULL,thread_routine,NULL);
}
sleep();
for(i=;i<THREADS;i++)
{
pthread_cancel(tid[i]);
pthread_join(tid[i],&result);
if(result == PTHREAD_CANCELED)
printf("thread %d cancelled\n",i);
else
printf("thread %d was not cancelled\n",i);
}
return ;
}
在一套“转包”功能的程序中,当分包线程在进行中时,承包线程被取消,这时不希望分包线程继续运行。可以在承包线程清除处理函数中取消每个分包线程,
如果原来是连接分包线程,它们将继续消费一些资源直到它们被连接或分离。这时应在承包线程清除处理函数中使用pthread_detach立即分离它。
代码示例如下:
#include<stdio.h>
#include<pthread.h>
#define THREADS 5
typedef struct send_tag
{
pthread_t sid[THREADS];
}send_t;
void *send_routine(void *arg)
{
int counter;
for(counter=;;counter++)
if(counter%==)
pthread_testcancel();
}
void cleanup(void *arg)
{
send_t *send = (send_t*)arg;
int i;
for(i=;i<THREADS;i++)
{
pthread_cancel(send->sid[i]);
pthread_detach(send->sid[i]);
printf("cleanup:cancelled %d\n",i);
}
}
void *thread_routine(void *arg)
{
send_t send;
int i;
void *result;
for(i=;i<THREADS;i++)
{
pthread_create(&send.sid[i],NULL,send_routine,NULL);
}
pthread_cleanup_push(cleanup,(void*)&send);
for(i=;i<THREADS;i++)
pthread_join(send.sid[i],&result);
pthread_cleanup_pop();
}
int main(void)
{
pthread_t tid;
void *result;
pthread_create(&tid,NULL,thread_routine,NULL);
sleep();
pthread_cancel(tid);
pthread_join(tid,&result);
return ;
}
参考资料:《POSIX多线程程序设计》 pp.120-137
posix多线程--线程取消的更多相关文章
- POSIX多线程—线程基本概念
http://blog.csdn.net/livelylittlefish/article/details/7957007 作者:阿波链接:http://blog.csdn.net/livelylit ...
- posix多线程--线程私有数据
1.当多个线程共享一个变量时,将该变量定义为静态或外部变量,使用互斥量确保共享变量的安全访问.如果每个线程都需要一个私有变量值,则该值成为线程的私有数据.程序创建一个键,每个线程独立地设定或得到自己的 ...
- POSIX多线程
全文共分四部分: POSIX多线程—概述 POSIX多线程—异步编程举例 POSIX多线程—线程基本概念 POSIX多线程—互斥量概述 POSIX多线程—概述 Content 1. ...
- POSIX 线程取消点的 Linux 实现
http://blog.csdn.net/stevenliyong/article/details/4364039 原文链接:http://blog.solrex.cn/articles/linux- ...
- .NET 异步多线程,Thread,ThreadPool,Task,Parallel,异常处理,线程取消
今天记录一下异步多线程的进阶历史,以及简单的使用方法 主要还是以Task,Parallel为主,毕竟用的比较多的现在就是这些了,再往前去的,除非是老项目,不然真的应该是挺少了,大概有个概念,就当了解一 ...
- 多线程的异常处理、线程取消、临时变量、lock
异步多线程的异常,抓不到,因为是在子线程执行. #region 多线程的异常处理.线程取消.临时变量.lock { try { List<Task> list = new List< ...
- .NET异步多线程,Thread,ThreadPool,Task,Parallel,异常处理,线程取消
今天记录一下异步多线程的进阶历史,以及简单的使用方法 主要还是以Task,Parallel为主,毕竟用的比较多的现在就是这些了,再往前去的,除非是老项目,不然真的应该是挺少了,大概有个概念,就当了解一 ...
- posix多线程--三种基本线程编程模型
本文介绍了三种构建线程解决方案的方式. 一.流水线:每个线程执行同一种操作,并把操作结果传递给下一步骤的线程. 代码示例如下:终端输入一个int值,每个线程将该值加1,并将结果传给下一个线程. #in ...
- C# 多线程总结 异常处理 线程取消 锁(lock)
那么什么时候能用多线程? 任务能并发的时候 多线程能干嘛?提升速度/优化用户体验 网站首页:A数据库 B接口 C分布式服务 D搜索引擎,适合多线程并发,都完成后才能返回给用户,需要等待WaitAll列 ...
随机推荐
- 【教程】HTML5+JavaScript编写flappy bird
作者: 风小锐 新浪微博ID:永远de风小锐 QQ:547953539 转载请注明出处 PS:新修复了两个bug,已下载代码的同学请查看一下 大学立即要毕业了. ...
- CSS3 calc()函数使用
1.calc是什么? calc是英文单词calculate(计算)的缩写,用于动态计算长度值. calc()函数支持 "+", "-", "*&quo ...
- 编译时:virtual memory exhausted: Cannot allocate memory(转)
一.问题 当安装虚拟机时系统时没有设置swap大小或设置内存太小,编译程序会出现virtual memory exhausted: Cannot allocate memory的问题,可以用swap扩 ...
- Oracle使用——PLSQL的中文乱码显示全是问号
问题 这两天刚将PLSQL与Oracle配置好,但是在PLSQL中插入数据时.出现一个问题,PLSQL中的表里无法显示中文,中文无法保存.无法输出.中文在表中显示问号.如图: 原因 经过一番查证,发现 ...
- 【Docker】常用命令
1.查看正在运行的容器 [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND ...
- google kaptcha 验证码组件使用简介
kaptcha 是一个非常实用的验证码生成工具.有了它,你可以生成各种样式的验证码,因为它是可配置的.kaptcha工作的原理是调用 com.google.code.kaptcha.servlet.K ...
- 快速搭建Seeddms文档管理系统
Seddms文档管理系统是开源的 环境: Redhat6.5 lamp 01.LAMP的安装 安装请看:http://www.cnblogs.com/xiaochina/p/6442337.html ...
- delphi實現按键精靈的功能
unit kbKernel; interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Fo ...
- java导出文件IE/Google文件名乱码兼容
导出文件名乱码解决方案: String agent = request.getHeader("User-Agent"); boolean isMSIE = (agent != ...
- hdu--DFS
DFS Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...