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列 ...
随机推荐
- Java从零开始学一(环境配置)
一.JDK的下载和安装 1.下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151. ...
- Jsp之神笔记
JSP笔记 Tomcatserver port: port就是指的某一个程序网络入口,Tomcat的初始化port为:8080: port的个数:256*256=65536个: 一般常见协议的缺省po ...
- jquery 圆形进度条
最近手里面的项目需要完成这个对设备性能的检测显示功能,需要使用到圆形进度条这样的效果,网上找了一圈,有很多相当的插件,找到:circliful 插件,看了他的使用说明比较的方便,于是就下载了它并将自己 ...
- SettingsEclipse
迁移时间--2017年5月20日08:45:07 CreateTime--2016年11月15日11:07:44Author:Marydon --------------------------- ...
- getpass模块
# -*- coding: utf-8 -*- #python 27 #xiaodeng #getpass模块 import getpass ''' >>> help(getpass ...
- c# 判断端口是否被占用
这里主要用到:命名空间System.Net.NetworkInformation下定义了一个名为IPGlobalProperties的类 具体代码 class PortHelper { #region ...
- java Properties的用法
Properties是一个特殊的Map,因为和IO流牵扯到了一块…… import java.io.BufferedReader;import java.io.File;import java.io. ...
- Linux下TCP最大连接数受限问题
一. 文件数限制修改1.用户级别查看Linux系统用户最大打开文件限制:# ulimit -n1024 (1) vi /etc/security/limits.confmysql soft nofil ...
- word技巧-文本转化表格
工作中不断学习,总能得到一点点成就感! 样例:
- te
var option = {}; $(function() { /* var taskId = ${pd.taskId}; */ var taskId = "1470880530369&qu ...