神农架网站建设,如何线上推广自己产品,搜索引擎seo优化怎么做,qq在线登陆聊天网页版线程退出回调函数 专栏内容#xff1a; 参天引擎内核架构 本专栏一起来聊聊参天引擎内核架构#xff0c;以及如何实现多机的数据库节点的多读多写#xff0c;与传统主备#xff0c;MPP的区别#xff0c;技术难点的分析#xff0c;数据元数据同步#xff0c;多主节点的…线程退出回调函数 专栏内容 参天引擎内核架构 本专栏一起来聊聊参天引擎内核架构以及如何实现多机的数据库节点的多读多写与传统主备MPP的区别技术难点的分析数据元数据同步多主节点的情况下对故障容灾的支持。 手写数据库toadb 本专栏主要介绍如何从零开发开发的步骤以及开发过程中的涉及的原理遇到的问题等让大家能跟上并且可以一起开发让每个需要的人成为参与者。 本专栏会定期更新对应的代码也会定期更新每个阶段的代码会打上tag方便阶段学习。 开源贡献 toadb开源库 个人主页我的主页 管理社区开源数据库 座右铭天行健君子以自强不息地势坤君子以厚德载物. 文章目录 线程退出回调函数前言概述接口说明使用说明示例代码执行结果总结结尾 前言
现代的CPU都是多core处理器而且在intel处理器中每个core又可以多个processor形成了多任务并行处理的硬件架构在服务器端的处理器上架构又有一些不同传统的采用SMP也就是对称的多任务处理架构每个任务都可以对等的访问所有内存外设等而如今在ARM系列CPU上多采用NUMA架构它将CPU核分了几个组给每个组的CPU core分配了对应的内存和外设CPU访问对应的内存和外设时速度最优跨组访问时性能会降底一些。
随着硬件技术的持续发展它们对一般应用的性能优化能力越来越强同时对于服务器软件的开发提出更高要求要想达到极高的并发和性能就需要充分利用当前硬件架构的特点对它们进行压榨。那么我们的应用至少也是要采用多任务架构不管是多线程还是多进程的多任务架构才可以充分利用硬件的资源达到高效的处理能力。
当然多任务框架的采用不仅仅是多线程的执行需要对多任务下带来的问题进行处理如任务执行返回值获取任务间数据的传递任务执行次序的协调当然也不是任务越多处理越快要避免线程过多导致操作系统夯住也要防止任务空转过快导致CPU使用率飙高。
本专栏主要介绍使用多线程与多进程模型如何搭建多任务的应用框架同时对多任务下的数据通信数据同步任务控制以及CPU core与任务绑定等相关知识的分享让大家在实际开发中轻松构建自已的多任务程序。
概述
在线程运行的过程中会有一些线程私有的数据在退出时需要线程自己来清理或者在线程退出时需要通知其它线程。在实际线程运行时对于正常预期的退出我们可以添加代码进行处理但是对于线程异常处理部分有些异常需要线程立即退出这些地方我们很难预期。
如何在线程退出时自动调用我们定义的清理函数呢
线程库的设计者已经早早就考虑到了这一点设计了退出清理回调函数的栈线程退出时按压入栈的次序依次从栈顶弹出回调函数执行。下面我们来看它们的详细使用方法。
接口说明
void pthread_cleanup_push(void (*routine)(void*), void *arg);
void pthread_cleanup_pop(int execute);参数说明 routine, 用户定义的清理函数 arg, 用户定义的清理函数的入参 execute, 是否要执行弹出的清理函数取值为0时不执行大于0执行
使用说明
清理回调机制的使用分为两个阶段
装载清理函数
在线程开始阶段将定义的清理函数压入栈当有多个清理函数时压栈的顺序需要用户自定义尽量与资源申请的顺序保持一致避免清理顺序错位
需要注意的是该步骤最好在没有错误发生或者资源申请之前。
清理函数执行
在线程处理完成后对清理函数弹出栈在弹出栈的同时还可以选择是否执行相应的清理函数如果是正常执行可能已经释放了相关资源。
当异常发生时线程会提前退出此时用户没有机会操作清理函数栈也没有机会选择清理函数是否需要执行在这种清况下线程库会自动从栈中依次弹出清理函数并且默认都会执行。
下面我们用两个线程来模拟正常退出和异常提前退出的情况。
示例代码
/* * created by senllang 2023/12/24 * mail : studysenllang.onaliyun.com * Copyright (C) 2023-2023, senllang*/
#include pthread.h
#include stdlib.h
#include stdio.h
#include string.h#define THREAD_NAME_LEN 32
typedef struct ThreadData
{char threadName[THREAD_NAME_LEN];unsigned long threadId;
}ThreadData;__thread ThreadData *pthreadData NULL;void threadCleanUp(void* arg)
{char *str (char *)arg;if(pthreadData ! NULL){printf([%lu][%s]cleanup process (%s)\n, pthreadData-threadId, pthreadData-threadName, str);free(pthreadData);pthreadData NULL;}else {printf([%lu] no work will be doing (%s). \n, pthread_self(), str);}return;
}void* thr1Func(void* arg)
{char *parg (char *)arg;pthreadData (ThreadData *)malloc(sizeof(ThreadData));memset(pthreadData, sizeof(ThreadData), 0x00);strncpy(pthreadData-threadName, parg, THREAD_NAME_LEN);pthreadData-threadId pthread_self();pthread_cleanup_push(threadCleanUp, (char*)first handler);pthread_cleanup_push(threadCleanUp, (char*)second handler);printf([%lu][%s]cleanup process push completed. \n, pthreadData-threadId, pthreadData-threadName);/* cleanup process will not be running. */pthread_cleanup_pop(1);pthread_cleanup_pop(1);return NULL;
}void* thr2Func(void* arg)
{int ret 2;char *parg (char *)arg;pthreadData (ThreadData *)malloc(sizeof(ThreadData));memset(pthreadData, sizeof(ThreadData), 0x00);strncpy(pthreadData-threadName, parg, THREAD_NAME_LEN);pthreadData-threadId pthread_self();pthread_cleanup_push(threadCleanUp, (char*)first handler);pthread_cleanup_push(threadCleanUp, (char*)second handler);printf([%lu][%s]cleanup process push completed. \n, pthreadData-threadId, pthreadData-threadName);/* make a error, exiting */if(ret 2)pthread_exit(ret);pthread_cleanup_pop(0);pthread_cleanup_pop(0);
}int main(int argc, char* argv[])
{int err;pthread_t tid1, tid2, tid3;void *ret;err pthread_create(tid1, NULL, thr1Func, thread 1);if(0 ! err)perror(cant create thread 1);err pthread_create(tid2, NULL, thr2Func, thread 2);if(0 ! err)perror(cant create thread 2);pthread_join(tid1, ret);pthread_join(tid2, ret);return 0;
}
总共创建两个线程每个线程都有一个本地数据的指针在线程运行时动态申请内存为每个线程压入了两个清理函数
线程一正常退出选择执行清理函数线程二模拟出错时异常提前退出而在正常退出时我们选择不执行清理函数
执行结果
[senllanghatch example_05]$ make
gcc -I./ -DTEST_PRO -lpthread -g -c cleanupThreads.c
gcc -I./ -DTEST_PRO -lpthread -g cleanupThreads.o -o hatch-0-01
[senllanghatch example_05]$ ./hatch-0-01
[140455969638144][thread 2]cleanup process push completed.
[140455978030848][thread 1]cleanup process push completed.
[140455978030848][thread 1]cleanup process (second handler)
[140455978030848] no work will be doing (first handler).
[140455969638144][thread 2]cleanup process (second handler)
[140455969638144] no work will be doing (first handler).从结果可以看到线程一退出时两个清理函数都执行了。 线程二异常退出时两个清理函数也都执行了虽然我们在退出时选择不执行清理函数但是系统在异常时自动弹出并默认执行了所有清理函数
总结
线程退出时的清理函数栈在实际应用程序代码设计时会让代码运行的更加健壮让多线程下不论是异常退出还是正常退出都有机会来对线程中用户资源的清理。
本文所涉及的代码已经上传到工程hatchCode, 在multipleThreads/example_05目录下请大家点star后续文章的代码也会上传到此工程。
结尾 非常感谢大家的支持在浏览的同时别忘了留下您宝贵的评论如果觉得值得鼓励请点赞收藏我会更加努力 作者邮箱studysenllang.onaliyun.com 如有错误或者疏漏欢迎指出互相学习。