1. 线程创建和取消函数接口
线程创建的函数原型:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
thread参数:新线程的TID
attr参数:线程属性
start_routine参数:线程例程,也就是如果线程创建成功,线程立即去执行的函数
arg参数:线程例程的参数
对线程创建函数的使用需要注意以下几点:
- 线程例程指的是:线程创建成功后线程立即执行的函数
- POSIX线程库的所有API对返回值的处理原则是一致的:成功返回0,失败返回错误码errno
- 线程属性如果设置为NULL,则会创建一个标准属性的线程
线程取消的函数原型:
int pthread_cancel(pthread_t thread);
thread参数:线程TID
当线程互道一个取消请求时,它将会如何表现取决于两点:1. 线程当前的取消状态 2. 线程当前的取消类型
- 线程当前的取消状态:一种是PTHREAD_CANCEL_ENABLE,该状态是线程默认的,表示线程可以接受取消请求。另一种是PTHREAD_CANCEL_DISABLE,该状态表示关闭取消请求,不对其响应
- 线程当前的取消类型:在线程接受取消请求的情况下,线程如何停下来取决于两种不同的响应取消类型,一种是PTHREAD_CANCEL_DEFERRED,表示延迟响应。另一种是PTHREAD_CANCEL_ASYNCHRONOUS,表示立即响应
压栈或弹栈线程的取消处理的函数原型:
由于线程在任何时刻都有可能持有互斥锁,信号量等资源,一旦被取消很可能导致别的线程死锁,因此如果一条线程的确可以取消,那么在该线程被取消之前必须使用相应的API函数来为将来可能出现的取消请求注册“处理例程”,让这些例程自动释放持有的资源
void pthread_cleanup_push(void (*routine)(void *),void *arg);
routine 参数:线程的取消处理例程
arg 参数:储存线程退出值的内存指针
void pthread_cleanup_pop(int execute);
execute 参数:如果是0,弹栈线程的取消处理例程,但不执行该例程;如果非0,弹栈线程的取消处理例程,并执行该例程
压栈或弹栈线程的取消处理的函数的使用需要注意以下几点:
- 使用pthread_cleanup_push()可以为线程的取消请求压入多个处理例程,这些例程会以栈的形式保留起来,在线程被取消之后,它们可以以弹栈的后进先出的形式依次被执行
- pthread_cleanup_push()和pthread_cleanup_pop()这两个函数必须配套使用,而且必须出现在同一层代码块种
2. 线程创建和取消代码示例
以下代码展示了如何创建一个线程,以及该线程如何正确地处理该取消请求
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t m; //线程锁
void handler(void *args){
pthread_mutex_unlock(&m); //解锁
}
void * routine(void *args){ //线程例程
//加锁前,将handler压入线程取消处理例程的栈中,以防中途被取消。如果中途被取消,执行handler
pthread_cleanup_push(handler, NULL);
pthread_mutex_lock(&m);
printf("[%u]:[%s] abtained the mutex\n", (unsigned)pthread_self(), __FUNCTION__);
sleep(10); //在此线程睡眠期间如果收到取消请求,则handler被执行
//解锁后,将handler弹出来,但并不执行它
pthread_mutex_unlock(&m);
pthread_cleanup_pop(0);
//线程退出
pthread_exit(NULL);
}
int main(int argc, char**argv){
pthread_mutex_init(&m, NULL); //初始化线程锁
//创建线程,并让线程执行例程
pthread_t tid;
pthread_create(&tid, NULL, routine, NULL);
//等待1秒后,向子线程发送一个取消请求
sleep(1);
pthread_cancel(tid);
//此时子线程被取消了,但被handler自动释放,因此主线程可以加锁
pthread_mutex_lock(&m);
printf("[%u]:[%s] abtained the mutex\n", (unsigned)pthread_self(), __FUNCTION__);
pthread_mutex_unlock(&m);
return 0;
}