线程的取消 线程的取消状态 线程取消点 验证线程被取消时 系统自动调用线程清理函数 线程的取消类型 当线程执行以下动作时会调用清理函数 线程退出清理函数 弹出清理函数
线程的取消
#include <pthread.h>
/*
*功能:
* 取消线程
*参数:
* thread:目标线程 ID
*return:
* 成功:0
* 失败:出错编号
*/
int pthread_cancel(pthread_t thread);
pthread_cancel 函数的实质是发信号给目标线程 thread, 使目标线程退出
此函数只是发送终止信号给目标线程, 不会等待取消目标线程执行完才返回
然而发送成功并不意味着目标线程一定就会终止, 线程被取消时, 线程的取消属性会决定线程能否被取消以及何时被取消
线程的取消状态
即线程能不能被取消
线程取消点
即线程被取消的地方
线程的取消类型
在线程能被取消的状态下, 是立马被取消结束还是执行到取消点的时候被取消结束
线程的取消状态
/*
*功能:
* 在 Linux 系统下, 线程默认可以被取消
* 编程时可以通过 pthread_setcancelstate 函数设置线程是否可以被取消
*参数:
* state:
* PTHREAD_CANCEL_DISABLE: 不可以被取消
* PTHREAD_CANCEL_ENABLE: 可以被取消
* old_state:
* 保存调用线程原来的可取消状态的内存地址
*/
pthread_setcancelstate(int state, int *old_state);
验证设置线程能 否被取消, 然后看线程能不能被取消
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
void *thread_cancel(void *arg);
int main(int argc, char *argv[])
{
pthread_t tid1;
int ret = 0;
pthread_create(&tid1, NULL, thread_cancel, NULL);
if(ret != 0)
{
perror("pthread_create");
}
sleep(3);
pthread_cancel(tid1);
pthread_join(tid1, NULL);
return 0;
}
void *thread_cancel(void *arg)
{
//pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
while(1)
{
printf("this is my new thread_cancel\n");
sleep(1);
}
return NULL;
}
线程的取消点
/*
*功能:
* 线程被取消后,该线程并不是马上终止,默认情况下线程执行到消点时才能被终止
* 编程时可以通过pthread_testcancel 函数设置线程的取消点
* 当别的线程取消调用此函数的线程时候,被取消的线程执行到此函数时结束
*/
void pthread_testcancel(void);
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
void *thread_cancel(void *arg);
int main(int argc, char *argv[]);
{
pthread_t tid1;
int ret = 0;
pthread_create(&tid1, NULL, thread_cancel, NULL);
if(ret != 0)
{
perror("pthread_create");
}
sleep(3);
pthread_cancel(tid1);
pthread_join(tid1, NULL);
return 0;
}
void *thread_cancel(void *arg)
{
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
while(1)
{
pthread_testcancel();
}
return NULL;
}
线程的取消类型
/*
*功能:
* 线程被取消后,该线程并不是马上终止,默认情况下线程执行到消点时才能被终止
* 编程时可以通过pthread_setcanceltype 函数设置线程是否可以立即被取消
*参数:
* type:
* PTHREAD_CANCEL_ASYNCHRONOUS: 立即取消
* PTHREAD_CANCEL_DEFERRED: 不立即被取消
* oldtype: 保存调用线程原来的可取消类型的内存地址
*/
pthread_setcanceltype(int type, int *oldtype);
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
void *thread_cancel(void *arg);
int main(int argc, char *argv[])
{
pthread_t tid1;
int ret = 0;
pthread_create(&tid, NULL, thread_cancel, NULL);
if(ret != 0)
{
perror("pthread_create");
}
sleep(3);
pthread_cancel(tid1);
pthread_join(tid1, NULL);
return 0;
}
void *thread_cancel(void *arg)
{
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
//pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
while(1);
return0;
}
线程退出清理函数
和进程的退出清理一样, 线程也可以注册它退出时要调用的函数, 这样的函数称为线程清理处理程序(threadcleanup handler)
注意:
线程可以建立多个清理处理程序
处理程序在栈中, 故它们的执行顺序与它们注册时的顺序相反
注册清理函数
#include <pthread.h>
/*
*功能:
* 将清除函数压栈。 即注册清理函数
*参数:
* routine: 线程清理函数的指针
* arg: 传给线程清理函数的参数
*/
void pthread_cleanup_push(void(*routine)(void *),void *arg);
弹出清理函数
#include <pthread.h>
/*
*功能:
* 将清除函数弹栈, 即删除清理函数
*参数:
* execute: 线程清理函数执行标志位
* 非 0,弹出清理函数,执行清理函数
* 0,弹出清理函数,不执行清理函数
*/
void pthread_cleanup_pop(int execute);
当线程执行以下动作时会调用清理函数:
调用 pthread_exit 退出线程
响应其它线程的取消请求
用非零 execute 调用 pthread_cleanup_pop
无论哪种情况 pthread_cleanup_pop 都将删除上一次 pthread_cleanup_push 调用注册的清理处理函数
验证线程调用 pthread_exit 函数时, 系统自动调用线程清理函数
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
void cleanup(void *arg);
void *thread(void *arg);
int main(int argc, char *argv[])
{
pthread_t tid;
//创建线程
pthread_create(&tid, NULL, thread, NULL);
pthread_join(tid, NULL);
printf("process is dying\n");
return 0;
}
void cleanup(void *arg)
{
printf("clean up ptr = %s\n",(char *)arg);
free((char *)arg);
}
void *thread(void *arg)
{
char *ptr = NULL;
//创建线程清理
printf("this is new thread\n");
ptr = (char *)malloc(100);
pthread_cleanup_push(cleanup, (void *)(ptr));
bzero(ptr, 100);
strcpy(ptr, "memory from malloc");
printf("before exit\n");
pthread_exit(NULL);
sleep(3);
//push 与 pop配对使用
printf("before pop\n");
pthread_cleanup_pop(1);
return NULL;
}
验证线程被取消时, 系统自动调用线程清理函数
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
void cleanup(void *arg);
void *thread(void *arg);
int main(int argc, char *argv[])
{
pthread_t tid;
pthread_create(&tid, NULL, thread, NULL);
sleep(1);
printf("before cancel\n");
//子线程响应 pthread_cancel 后, 会执行线程处理函数
pthread_cancel(tid);
pthread_join(tid, NULL);
printf("process is dying\n");
return 0;
}
void cleanup(void *arg)
{
printf("clean up ptr = %s\n",(char *)arg);
free((char *)arg);
}
void *thread(void *arg)
{
char *ptr = NULL;
printf("this is new thread\n");
ptr = (char *)malloc(100);
pthread_cleanup_push(cleanup, (void *)(ptr));
bzero(ptr, 100);
strcpy(ptr, "memory form malloc");
sleep(3);
printf("before pop\n");
pthread_cleanup_pop(1);
return NULL;
}
验证调用 pthread_cleanup_pop 函数时, 系统自动调用线程清理函数
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
void cleanup_func1(void *arg);
void cleanup_func2(void *arg);
void *thread(void *arg);
int main()
{
pthread_t tid;
pthread_create(&tid, NULL, thread, NULL);
pthread_join(tid, NULL);
printf("process is dying\n");
return 0;
}
void cleanup_func1(void *arg)
{
printf("in cleanup funcl\n");
printf("clean up ptr = %s\n",(char *)arg);
free((char *)arg);
}
void cleanup_func2(void *arg)
{
printf("in cleanup func2\n");
}
void *thread(void *arg)
{
char *ptr = NULL;
//创建线程清理
printf("this is new thread\n");
ptr = (char *)malloc(100);
pthread_cleanup_push(cleanup_func1, (void *)(ptr));
pthread_cleanup_push(cleanup_func2, NULL);
bzero(ptr, 100);
strcpy(ptr, "memory from malloc");
printf("before pop\n");
pthread_cleanup_pop(1);
printf("before pop\n");
pthread_cleanup_pop(1);
return NULL;
}