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从零开始学十二(构造方法)
一.构造方法 构造方法的主要目的是为类中的属性初始化 二.构造方法的定义格式 class 类名称{ 访问权限 类名称(类型1 参数1,类型2 参数2,…){ 程序语句 ; … // 构造方法没有 ...
- GraphQL返回分页对象
private GraphQLOutputType testUserOutputType; private GraphQLOutputType pageType; private void initO ...
- client高性能组件化框架React简单介绍、特点、环境搭建及经常使用语法
[本文源址:http://blog.csdn.net/q1056843325/article/details/54729657 转载请加入该地址] 明天就是除夕了 预祝大家新春快乐 [ ]~( ̄▽ ̄) ...
- eclipse Java代码折叠工具
eclipse Java代码折叠工具 CreateTime--2018年5月17日15点09分 Author:Marydon 1.问题描述 eclipse自带的代码折叠工具,无法折叠try{}ca ...
- fread与read的差别(文件io补充)
这里有一个我们常常提出的问题就是fread,read的差别.(当然这两个分别代表了操作文件系统的两套不同的函数,包含open,read, write, seek 等). 一.他们的差别就是一个(rea ...
- 如何通过from语句调用模块的变量名?
# -*- coding: utf-8 -*- #python 27 #xiaodeng #如何通过from语句调用模块的变量名? #my.py def printer(x): print x #如何 ...
- android.widget.BaseAdapter调用DataSetObservable.notifyChanged/Invalidated
在android.widget.BaseAdapter类中定义了两个notifyDataXXX方法. public void notifyDataSetChanged() { mDataSet ...
- 原创:微信小程序调用PHP后台接口,解析纯html文本
---效果图片预览--- 1.微信js动态传参:wx.request({ url: 'https://m.****.com/index.php/Home/Xiaoxxf/activ ...
- jquery json ajax三级联动
province_city_area.jsp <%@ page language="java" pageEncoding="UTF-8"%> < ...
- html5中的FileReader对象
表单中有图片选项,选中图片文件之后要求可以预览.这个功能很多控件都封装好了,但是它们的底层都是FileReader对象. FileReader对象提供了丰富的功能,包括以二进制.以文本方式读取文件内容 ...