lienhua34
2014-11-24

1 取消线程

pthread 提供了pthread_cancel 函数用于请求取消同一进程中的其他线程。

#include <pthread.h>

int pthread_cancel(pthread_t tid);

返回值:若成功则返回0,否则返回错误编码

pthread_cancel 调用并不会立即终止目标线程,而只是向目标线程发出取消请求。调用线程不等待目标线程终止,在默认情况下,目标线程在取消请求发出以后还是继续运行的,直到目标线程到达某个取消点。取消点是线程检查是否被取消并按照请求进行动作的一个位置。

下面我们来看个线程取消的例子。主线程创建一个新线程,新线程循环睡眠 5 秒钟然后返回 2. 而主线程在创建新线程之后睡眠 2 秒钟便调用pthread_cancel 来请求取消新线程。最后获取新线程的退出状态。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h> void *
my_thread(void *arg)
{
int i=; printf("[new thread]: I will sleep 5 seconds.\n");
while (i < ) {
sleep();
i = i + ;
printf("[new thread]: %d\n", i);
}
printf("[new thread]: exit now.\n");
return ((void *));
} int
main(void)
{
int err;
pthread_t tid;
void *tret; err = pthread_create(&tid, NULL, my_thread, NULL);
if ( err != ) {
printf("can't create thread: %s\n", strerror(err));
exit(-);
} sleep();
printf("[main thread]: cancel new thread.\n");
err = pthread_cancel(tid);
if (err != ) {
printf("can't cancel thread: %s\n", strerror(err));
exit(-);
} err = pthread_join(tid, &tret);
if (err != ) {
printf("can't join with new thread: %s\n", strerror(err));
exit(-);
} else {
if (PTHREAD_CANCELED == tret) {
printf("new thread has been canceled.\n");
} else {
printf("new thread exit code: %d\n", (int)tret);
}
} exit();
}

编译该程序,生成并执行文件pthread_cancel_demo,

lienhua34:demo$ gcc -o pthread_cancel_demo -pthread pthread_cancel_demo.c
lienhua34:demo$ ./pthread_cancel_demo
[new thread]: I will sleep seconds.
[new thread]:
[main thread]: cancel new thread.
new thread has been canceled.

如果某个线程响应了取消请求相当于调用了参数为PTHREAD_CANCELED的pthread_exit 函数。

2 线程取消属性

前面学习了可以通过pthread_attr_t 结构来控制线程的属性。但是有两个与线程取消的属性没有包含在pthread_attr_t 结构中,它们是可取消状态和可取消类型。

2.1 可取消状态

可取消状态属性是个使能属性,控制了线程是否要响应其他线程的取消请求。该属性可以是PTHREAD_CANCEL_ENABLE,或者是PTHREAD_CANCEL_DISABLE。线程的可取消属性默认为前者。如果设置为后者,则线程将不会响应取消请求,不过取消请求对于该线程来说处于未决状态,当可取消状态再次变为PTHREAD_CANCEL_ENABLE 时,线程将在下个取消点上对所有未决的取消请求进行处理。

线程可以通过调用pthread_setcancelstate 函数来修改其可取消状态。

#include <pthread.h>

int pthread_setcancelstate(int state, int *oldstate);

返回值:若成功则返回0,否则返回错误编号

该函数将线程的当前可取消状态设置为 state,并通过 oldstate 返回原来的可取消状态。

下面我们来看那个例子,我们在上面的pthread_cancel_demo.c 程序的新线程入口函数my_thread 的开始调用pthread_setcancelstate 函数将新线程的可取消状态设置为PTHREAD_CANCEL_DISABLE。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h> void *
my_thread(void *arg)
{
int i=;
int err;
err = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
if (err != ) {
printf("[new thread]: can't set cancel state: %s\n", strerror(err));
}
printf("[new thread: disable cancel state.\n"); printf("[new thread]: I will sleep 5 seconds.\n");
while (i < ) {
sleep();
i = i + ;
printf("[new thread]: %d\n", i);
}
printf("[new thread]: exit now.\n");
return ((void *));
} int
main(void)
{
int err;
pthread_t tid;
void *tret; err = pthread_create(&tid, NULL, my_thread, NULL);
if ( err != ) {
printf("can't create thread: %s\n", strerror(err));
exit(-);
} sleep();
printf("[main thread]: cancel new thread.\n");
err = pthread_cancel(tid);
if (err != ) {
printf("can't cancel thread: %s\n", strerror(err));
exit(-);
} err = pthread_join(tid, &tret);
if (err != ) {
printf("can't join with new thread: %s\n", strerror(err));
exit(-);
} else {
if (PTHREAD_CANCELED == tret) {
printf("new thread has been canceled.\n");
} else {
printf("new thread exit code: %d\n", (int)tret);
}
} exit();
}

编译该程序,生成并执行pthread_cancel_demo 文件,

lienhua34:demo$ gcc -o pthread_cancel_demo -pthread pthread_cancel_demo.c
lienhua34:demo$ ./pthread_cancel_demo
[new thread: disable cancel state.
[new thread]: I will sleep seconds.
[new thread]:
[main thread]: cancel new thread.
[new thread]:
[new thread]:
[new thread]:
[new thread]:
[new thread]: exit now.
new thread exit code:

从上面的运行结果与前一节的运行结果对比,我们可以看出将新线程的可取消状态设置为PTHREAD_CANCEL_DISABLE 后,新线程没有响应主线程的取消请求。

2.2 可取消类型

上面所说的线程在到达某个取消点的时候会去检查一下是否被取消。这种取消类型也称为延迟取消。另外,还有一种取消类型是异步取消。当线程的取消类型为异步取消时,线程可以在任意时间被取消。

线程可以通过调用pthread_setcanceltype 来修改线程的取消类型。

#include <pthread.h>

int pthread_setcanceltype(int type, int *oldtype);

返回值:若成功则返回0,否则返回错误编号

其中type参数可以是PTHREAD_CANCEL_DEFERRED(延迟取消), 或者PTHREAD_CANCEL_ASYNCHRONOUS(异步取消)。该函数将线程的当前可取消类型设置为 type,然后将原来的可取消类型通过 oldtype 参数返回。

(done)

UNIX环境编程学习笔记(28)——多线程编程(三):线程的取消的更多相关文章

  1. 孙鑫VC学习笔记:多线程编程

    孙鑫VC学习笔记:多线程编程 SkySeraph Dec 11st 2010  HQU Email:zgzhaobo@gmail.com    QQ:452728574 Latest Modified ...

  2. Python Web学习笔记之多线程编程

    本次给大家介绍Python的多线程编程,标题如下: Python多线程简介 Python多线程之threading模块 Python多线程之Lock线程锁 Python多线程之Python的GIL锁 ...

  3. 网络编程学习笔记:Socket编程

    文的主要内容如下: 1.网络中进程之间如何通信? 2.Socket是什么? 3.socket的基本操作 3.1.socket()函数 3.2.bind()函数 3.3.listen().connect ...

  4. linux网络编程学习笔记之五 -----并发机制与线程�

    进程线程分配方式 简述下常见的进程和线程分配方式:(好吧,我仅仅是举几个样例作为笔记...并发的水太深了,不敢妄谈...) 1.进程线程预分配 简言之,当I/O开销大于计算开销且并发量较大时,为了节省 ...

  5. python核心编程学习记录之多线程编程

  6. java网络编程学习笔记(四):线程池的实现

    package QQ; import java.util.LinkedList; /** * Created by hu on 2015/11/9. */ public class ThreadPoo ...

  7. 多线程编程学习笔记——async和await(一)

    接上文 多线程编程学习笔记——任务并行库(一) 接上文 多线程编程学习笔记——任务并行库(二) 接上文 多线程编程学习笔记——任务并行库(三) 接上文 多线程编程学习笔记——任务并行库(四) 通过前面 ...

  8. 多线程编程学习笔记——async和await(二)

    接上文 多线程编程学习笔记——async和await(一) 三.   对连续的异步任务使用await操作符 本示例学习如何阅读有多个await方法方法时,程序的实际流程是怎么样的,理解await的异步 ...

  9. 多线程编程学习笔记——async和await(三)

    接上文 多线程编程学习笔记——async和await(一) 接上文 多线程编程学习笔记——async和await(二) 五.   处理异步操作中的异常 本示例学习如何在异步函数中处理异常,学习如何对多 ...

  10. 多线程编程学习笔记——使用异步IO(一)

    接上文 多线程编程学习笔记——使用并发集合(一) 接上文 多线程编程学习笔记——使用并发集合(二) 接上文 多线程编程学习笔记——使用并发集合(三) 假设以下场景,如果在客户端运行程序,最的事情之一是 ...

随机推荐

  1. 问题-MethodAddress返回NIL?MethodAddress与published的关系?

    问题现象:有位朋友(397085381)在Q群里问“为什么书上的可以访问,而自己写的代码访问时为nil” 问题原因:因为要用“Self.MethodAddress('Test')”访问,方法必须放在“ ...

  2. 算法篇---java经典问题!!!

    问题一:==与equal的区别? ==和 equals 都是比较的,而前者是运算符,后者则是一个方法,基本数据类型和引用数据类型都可以使用运算符==,而只有引用类型数据才可以使用 equals,下面具 ...

  3. web前端开发与iOS终端开发的异同[转]

    * {-webkit-tap-highlight-color: rgba(0,0,0,0);}html {-webkit-text-size-adjust: none;}body {font-fami ...

  4. Thrift——栗子

    这张经典的图:黄色部分是用户实现的业务逻辑,褐色部分是根据Thrift定义的服务接口描述文件(IDL,接口定义语言)生成的客户端和服务端代码框架,红色部分是根据Thrift文件生成代码实现数据的读写操 ...

  5. Python-OpenCV快速教程

    一.Mat生成图片 面的简单代码就可以生成两种表示方式下,图6-1中矩阵的对应的图像,生成图像后,放大看就能体会到区别: import numpy as np import cv2 import ma ...

  6. 简单防范SYN_RECV攻击

    netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' 这条语句返回结果如下 TIME_WAIT FIN_WAIT1 ...

  7. android开发(33) 让 actionbar 透明2

    让 actionbar 的背景 透明 我需要一个 透明的actionbar ,找到如下方法实现: 1. 首先,设置ActionBar 浮动到主界面上来. 2. 然后,设置ActionBar的背景色,透 ...

  8. Java设计模式(3)建造者模式(Builder模式)

    Builder模式定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. Builder模式是一步一步创建一个复杂的对象,它允许用户可以只通过指定复杂对象的类型和内容就可以构 ...

  9. 使用VMware将Linux装在物理硬盘上,开机即可进入Linux

    我的笔记本上是双系统Windows和Linux .经常需要在两个系统间切换,很麻烦.于是我想到如果能用VMWare虚拟机加载物理硬盘中的系统,可以在需要时,直接启动另外一个系统.     注意:我的双 ...

  10. Ogre GpuProgram分析

    和前面讲解的Compositor一样,GpuProgram也对应一种资源文件,意思我们可以直接写一个文件来完成,不需要了解相关的类. 但是就和winform一样,直接拖控件能完成大部分工作,假如如果需 ...