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列 ...
随机推荐
- 从零开始学JavaScript三(变量)
一.变量 ECMAscript变量是松散型变量,所谓松散型变量,就是变量名称可以保存任何类型的数据,每个变量仅仅是一个用于保存值的占位符. 定义变量时要使用var操作符 如: var message; ...
- webpack entry和output配置属性
1.entry entry的三种配置方式: (1)传递字符串: 单个入口语法:传递一个字符串 entry: './src/js/main.js', (2)传递数组 将创建“多个主入口(multi-ma ...
- linux安装JDK环境,JDK6.0即java 1.6.0
下载 (1)更改权限:# chmod 755 jdk-1.6.0_23-linux-i586.rpm.bin 执行安装:# ./ jdk-1.6.0_23-linux-i586.rpm.bin 此步完 ...
- JVM内存管理、JVM垃圾回收机制、新生代、老年代以及永久代
内存模型 JVM运行时数据区由程序计数器.堆.虚拟机栈.本地方法栈.方法区部分组成,结构图如下所示. JVM内存结构由程序计数器.堆.栈.本地方法栈.方法区等部分组成,结构图如下所示: 1)程序计数器 ...
- CentOS 7 网络磁盘挂载到本地 并测试传输速度
本文中的配置只做测试使用,正式环境中考虑到安全,请自行结合网上介绍的配置细节完善配置内容. 首先明确两个概念,服务器和客户端(本地),我们要做的是将服务端的硬盘上的/home/liuyx 目录挂载到本 ...
- 腾讯云-搭建 WordPress 个人博客
搭建 WordPress 个人博客 准备 LNMP 环境 任务时间:30min ~ 60min LNMP 是 Linux.Nginx.MySQL 和 PHP 的缩写,是 WordPress 博客系统依 ...
- HTML5 CANVAS 弹幕插件
概述 修改了普通弹幕运动的算法,新增了部分功能 详细 代码下载:http://www.demodashi.com/demo/10595.html 修改了普通弹幕运动的算法,新增了部分功能,具体请参看附 ...
- Oracle EBS WMS功能介绍(二)
Oracle EBS WMS功能介绍(二) (版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处.否则请与本人联系,违者必究) 出货物流逻辑主要包括 1. 打包.能够进 ...
- 在ListView的右边添加字母列表
在ListView的右边添加字母列表,点击某个字母时,列表就滚动到预期位置. <!-- 数字和字母栏在标题栏下边并且停靠在右边 --> <com.txrj.sms.component ...
- JedisClient(示例)
拷贝 import java.io.IOException; import java.util.HashSet; import java.util.Map; import java.util.Set; ...