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多线程--线程取消的更多相关文章

  1. POSIX多线程—线程基本概念

    http://blog.csdn.net/livelylittlefish/article/details/7957007 作者:阿波链接:http://blog.csdn.net/livelylit ...

  2. posix多线程--线程私有数据

    1.当多个线程共享一个变量时,将该变量定义为静态或外部变量,使用互斥量确保共享变量的安全访问.如果每个线程都需要一个私有变量值,则该值成为线程的私有数据.程序创建一个键,每个线程独立地设定或得到自己的 ...

  3. POSIX多线程

    全文共分四部分: POSIX多线程—概述    POSIX多线程—异步编程举例    POSIX多线程—线程基本概念    POSIX多线程—互斥量概述 POSIX多线程—概述 Content 1. ...

  4. POSIX 线程取消点的 Linux 实现

    http://blog.csdn.net/stevenliyong/article/details/4364039 原文链接:http://blog.solrex.cn/articles/linux- ...

  5. .NET 异步多线程,Thread,ThreadPool,Task,Parallel,异常处理,线程取消

    今天记录一下异步多线程的进阶历史,以及简单的使用方法 主要还是以Task,Parallel为主,毕竟用的比较多的现在就是这些了,再往前去的,除非是老项目,不然真的应该是挺少了,大概有个概念,就当了解一 ...

  6. 多线程的异常处理、线程取消、临时变量、lock

    异步多线程的异常,抓不到,因为是在子线程执行. #region 多线程的异常处理.线程取消.临时变量.lock { try { List<Task> list = new List< ...

  7. .NET异步多线程,Thread,ThreadPool,Task,Parallel,异常处理,线程取消

    今天记录一下异步多线程的进阶历史,以及简单的使用方法 主要还是以Task,Parallel为主,毕竟用的比较多的现在就是这些了,再往前去的,除非是老项目,不然真的应该是挺少了,大概有个概念,就当了解一 ...

  8. posix多线程--三种基本线程编程模型

    本文介绍了三种构建线程解决方案的方式. 一.流水线:每个线程执行同一种操作,并把操作结果传递给下一步骤的线程. 代码示例如下:终端输入一个int值,每个线程将该值加1,并将结果传给下一个线程. #in ...

  9. C# 多线程总结 异常处理 线程取消 锁(lock)

    那么什么时候能用多线程? 任务能并发的时候 多线程能干嘛?提升速度/优化用户体验 网站首页:A数据库 B接口 C分布式服务 D搜索引擎,适合多线程并发,都完成后才能返回给用户,需要等待WaitAll列 ...

随机推荐

  1. Using QuickExec

    Fiddler's QuickExec box allows you to launch script-commands quickly. Keyboard Shortcuts Hit ALT+Q t ...

  2. Closing a window

    The obvious way to how to close a window is to click on the x mark on the titlebar. In the next exam ...

  3. /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory 错误:

    在安装tomcat时报了错: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory 本机环境: [root@AY1405 ...

  4. win10下Visual Studio 2015,C++ x64编译zlib

    前提安装了visual studio 2015      PS.几乎所有方式,x64的编译都会有点坑,鉴于网上的x86编译方式非常的多,所以不再累赘x86的编译方式 zlib下载源: 官网:http: ...

  5. 关于android屏幕适配的问题(drawable-xxxxxxxx,dp,sp,px等等),偶尔看到了android源代码,关于dpi的区分的值

    上一篇博客说了一下.9.png图片http://blog.csdn.net/qq_23195583/article/details/46737419 当然,点九的是指的能够进行拉伸的.那么假设图片不能 ...

  6. smokeping with tcpping centos 7 环境

    本次环境采用centos7,使用centos6的同学就洗洗睡吧,此外一定要做好时间同步,并且关闭防火墙以及selinux,不然安装可能会失败的哦.时间同步方式如下: yum install ntpda ...

  7. iOS实现在webview页面内点击链接,跳转指定App

    早上和UI刚谈到这个需求,然后自己试了一下,发现还是蛮简单的,记录一下: 思路分析: iOS内应用之间跳转都会用到 URL Schemes这个东西,简单的讲,这个就是用来定义app身份的一个id识别, ...

  8. JAVA RMI远程方法调用简单实例[转]

    RMI的概念 RMI(Remote Method Invocation)远程方法调用是一种计算机之间利用远程对象互相调用实现双方通讯的一种通讯机制.使用这种机制,某一台计算机上的对象可以调用另外 一台 ...

  9. JS打开新窗口防止被浏览器阻止的方法[转]

    本文实例讲述了JS打开新窗口防止被浏览器阻止的方法.分享给大家供大家参考.具体分析如下: 用传统的window.open()方式打开新窗口,会被浏览器阻止,那么,我们如何才能让JS打开新窗口不被浏览器 ...

  10. NSURLRequestCachePolicy 缓存策略

    1> NSURLRequestUseProtocolCachePolicy = 0, 默认的缓存策略, 如果缓存不存在,直接从服务端获取.如果缓存存在,会根据response中的Cache-Co ...