(1)为什么要使用线程清理函数
1.假设遇到取消请求,线程执行到了取消点,却没有来得及做清理动作(如动态申请的内存没有释放,申请的互斥量没有解锁等), 可能会导致错误的产生,比如死锁,甚至是进程崩溃。
2.为了避免这种情况,线程可以设置一个或多个清理函数,线程取消或退出时,会自动执行这些清理函数,以确保资源处于一致的状态。
(2)相关接口
void pthread_cleanup_push(void (*routine)(void *),void *arg);
void pthread_cleanup_pop(int execute);
注意:
1.Linux 就是用宏来实现的。这意味着这两个函数必须同时出现,并且属于同一个语法块(同一函数中)。
2. pthread_cleanup_push(clean_func,clean_arg);
......
if(cond)
pthread_cleanup_pop(0);
//在日常编码中很容易犯上面这种错误。因为 pthread_cleanup_push 和 phtread_cleanup_pop 的实现中包
//含了 { 和 } ,所以将 pop 放入 if{} 的代码块中,会导致括号匹配错乱,最终会引发编译错误。
3.可以注册多个清理函数
pthread_cleanup_push(clean_func_1,clean_arg_1)
pthread_cleanup_push(clean_func_2,clean_arg_2)
...
pthread_cleanup_pop(execute_2);
pthread_cleanup_pop(execute_1);
3.从 push 和 pop 的名字可以看出,这是栈的风格,后入先出,就是后注册的清理函数会先执行
其中 pthread_cleanup_pop 的用处是,删除注册的清理函数。如果参数是非 0 值,那么执行一次,再删除清理函数。否则的话,就直接删除清理函数。
(3)何时触发清理函数 (在Ubuntu16上实测) :
1.pthread_cancel:
1.线程取消前执行了pthread_cleanup_pop(0), 就不会执行清理函数
2.否则执行清理函数
2.pthread_exit()
1.如果在pthread_exit前执行了pthread_cleanup_pop(0), 清理函数不会执行
2.如果在pthread_exit前执行了pthread_cleanup_pop(1), 清理函数会执行
3.pthread_exit在pthread_cleanup_pop函数前被执行, 清理函数一定会执行
3.return()
1.如果在return前执行了pthread_cleanup_pop(0), 清理函数不会执行
2.如果在return前执行了pthread_cleanup_pop(1), 清理函数会执行
3.return在pthread_cleanup_pop函数前被执行, 清理函数一定不会执行