pthread_cancel函数注意事项
/**************************************************
相关函数:
#include <pthread.h>
int pthread_cancel(pthread_t thread)
成功返回0,失败返回错误码
**************************************************/
此函数是POSIX提供的用于取消同一进程中的其它线程,此函
数只发送取消请求,并不等待要取消的进程退出!线程可以
选择忽略或是选择其它动作!
需要注意的是:
当我们调用它取消一个已经获得互斥锁/匿名信号量/写锁....但
还未释放其所获得锁的线程时,如果此线程被取消,此后所有想
要获得此时执行任务的线程都将处于睡眠状态,直到此锁被释放.
为避免此问题的产生,我们可以调用一组函数:
/**************************************************
#include <pthread.h>
void pthread_cleanup_push(void (*routine)(void *), void *arg)
void pthread_cleanup_pop(int execute)
参数解释:routine为函数指针,arg为传递给routine的参数
execute为零时,从栈中删除注册的函数,删除后将再也
不被执行。
**************************************************/
这两个函数被称为线程清理处理程序,类似于atexit函数,我们
可以注册多个清理函数,当执行以下动作时我们所注册的函数将会
回调(执行顺序与注册顺序相反):
1.线程从pthread_exit(void *)函数退出时。
2.线程响应取消请求时。
3.执行pthread_cleanup_pop函数,execute参数为非零时。
这两个线程清理处理程序必须成对出现,必须处于同一作用域中,
否则会编译出错。
实例:
如何使用这些函数处理以上问题!
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <pthread.h>
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
void *count(void *arg)
{
int i=1;
while(1)
{
sleep(1);
printf("sec: %d\n", i++);
}
}
void handler(void *arg)
{
printf("[%u] is cancelled.\n", (unsigned)pthread_self());
pthread_mutex_t *pm = (pthread_mutex_t *)arg;
pthread_mutex_unlock(pm);
}
void *routine(void *arg)
{
#ifdef CLEANUP
pthread_cleanup_push(handler, (void *)&m);
#endif
pthread_mutex_lock(&m);
printf("[%u] lock the mutex!\n", (unsigned)pthread_self());
/*
** During sleep(), if the calling thread received a cancel-
** request and HASN'T established any cleanup handlers to
** unlock the mutex, it will leave the mutex a DEAD-LOCK
** state.
*/
sleep(2);
printf("[%u]: job finished!\n", (unsigned)pthread_self());
pthread_mutex_unlock(&m);
printf("[%u] unlock the mutex!\n", (unsigned)pthread_self());
/*
** NOTE:
**
** pthread_cleanup_push() and pthread_cleanup_pop() may be
** implemented as macro that expand to text containing '{'
** and '}', respectively. For this reason, the caller must
** user them pairly and ensure that they are paired within
** a same function and at the same lexical nesting level.
*/
#ifdef CLEANUP
pthread_cleanup_pop(0);
#endif
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
pthread_t t, t1, t2;
pthread_create(&t, NULL, count, NULL);
pthread_create(&t1, NULL, routine, NULL);
pthread_create(&t2, NULL, routine, NULL);
printf("[%u] ==> t1\n", (unsigned)t1);
printf("[%u] ==> t2\n", (unsigned)t2);
printf("[%u] ==> main\n", (unsigned)pthread_self());
sleep(1);
pthread_cancel(t1);
pthread_cancel(t2);
sleep(2);
pthread_mutex_lock(&m);
printf("[%u] locked the mutex!\n",
(unsigned)pthread_self());
pthread_mutex_unlock(&m);
exit(0);
}
pthread_cancel函数注意事项的更多相关文章
- js foreach函数 注意事项(break、continue)
foreach API说明: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Arra ...
- pthread_testcancel和pthread_cancel函数的简单示例
/*0.取消线程 int pthread_cancel(pthread_t thread); 设置取消点 void pthread_testcancel(void); 测试是否接收到取消请求,如果有, ...
- js自执行函数注意事项
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- c++虚函数注意事项
>在基类方法声明中使用关键字virtual,可以使该方法在基类及所有的派生类中是虚的 >如果使用指向对象的引用或指针来调用虚方法,程序将使用对象类型定义的方法,而不使用为引用或指针类型定义 ...
- OpenCV中cvWaitKey()函数注意事项
注意:这个函数是HighGUI中唯一能够获取和操作事件的函数,所以在一般的事件处理中,它需要周期地被调用,除非HighGUI被用在某些能够处理事件的环境中.比如在MFC环境下,这个函数不起作用.
- 内联汇编和JMP到内联函数注意事项
对于jmp类型的hook, 如果自己的过程没有使用_declspec(naked),那么系统会自动给添加一些额外的代码,控制堆栈平衡,但是这些额外的代码会破坏被hook函数的堆栈. 对于call类型的 ...
- MySqL触发器以及常用转换函数注意事项
1,触发器(http://www.cnblogs.com/zzwlovegfj/archive/2012/07/04/2576989.html) 1.MYSQL中触发器中不能对本表进行 i ...
- PLSQL 创建自定义函数注意事项
2017-6-8周四,今天遇到的需求是,从数据库中查找出某张表的某些数据,并将这些数据做简单的加减运算再得到结果集,没有思路,后来问辉哥,给我的建议是给这些运算封装成一个SQL函数,select选择字 ...
- js- DOM事件之按钮绑定函数注意事项
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...
随机推荐
- JS异步解决方案之概念理解-----------阻塞和非阻塞,同步和异步,并发和并行,单线程和多线程
首先记住一句话,JS是单线程的. 单线程意味着什么?单线程意味着 它不能依靠自己实现异步. JS实现的异步,往往都是靠 浏览器.Node 的机制(事件驱动.回调)实现的. 下面让我这个单身狗 以谈恋爱 ...
- Unity 行为树-节点间数据传递
一.引言 有以下小场景: 节点A:发现了 敌人. 节点B:追逐敌人. 对于同一个敌人物体,节点AB之间是如何传递数据 的呢? 二.数据传递的3种方式 1.共享变量:面板中创建局部或者全局的共享变量Te ...
- 华东交通大学2017年ACM“双基”程序设计竞赛 1009
Problem Description MDD随机生成了n(n<le5)个随机数x(x<=1e9),这n个随机数排成一个序列,MDD有q(q<=le5)个询问,每个询问给你一个a,问 ...
- Angular学习笔记之组件之间的交互
1.@Input:可设置属性 当它通过属性绑定的形式被绑定时,值会“流入”这个属性. 在子组件中使用,例如:@Input()name:string 父组件定义宾亮,并在父组件的模板中绑定,例如: 子组 ...
- BufferedReader readLine
import org.apache.commons.codec.binary.Base64;import org.apache.commons.codec.digest.DigestUtils; In ...
- (转)linux 系统下虚拟用户的作用
原文:http://blog.csdn.net/luoshao20120430/article/details/16900653 http://blog.csdn.net/u01 ...
- PHP session变量的销毁
1.何为session? 相当于一个客户端(可以是浏览器.app.ftp等其他,而且同一个浏览器多开几个又算是不同的客户端)对服务器的一个访问,这个期间服务器为此建立一个唯一的标示(session_i ...
- 精心收集的SSH框架的面试题汇总
Hibernate工作原理及为什么要用? 原理: 1. 读取并解析配置文件 2. 读取并解析映射信息,创建SessionFactory 3. 打开Sesssion 4. 创建事务Transation ...
- .net core mvc项目部署nginx报错一直显示404错误
遇到一个奇怪的问题,.net core mvc 项目部署到nginx上面,系统是linux,controller明明抛出500错误,但页面一直显示是404. 解决如下: 1.修改Startup.cs, ...
- Ionic2集成DevExtreme
安装Install DevExtreme Angular npm install --save devextreme devextreme-angular 或者在package.json 文件中增加依 ...