pthread实现定时器多数时间休眠却高CPU占用的问题与优化咨询
问题核心原因
CPU占用过高的根本原因是定时器创建时未初始化update_interval的内容,且update_interval指针永远非空,导致select的超时时间为垃圾值:
- 你在
my_timer_create中直接为update_interval、interval、start三个指针分配了内存,但没有初始化内存内容,也没有将指针置为NULL timer_count中判断if(t->update_interval)的逻辑完全失效,因为指针已经被malloc过,永远为真,会直接拷贝update_interval里的垃圾值作为select的超时时间- 绝大多数情况下垃圾值对应的超时时间为0,select会直接非阻塞返回,导致线程进入死循环,持续占用CPU
修复方案
- 修改定时器创建逻辑,合理初始化指针
将my_timer_create中提前分配三个timeval的逻辑删掉,默认把指针置为NULL,只有调用对应的set接口时才分配/赋值:
struct timer *my_timer_create() { int check; struct timer *t; int fd[2]; t = malloc(sizeof(*t)); // 初始化指针为NULL,不要提前分配内存 t->interval = NULL; t->update_interval = NULL; t->start = NULL; check = pipe(fd); if(-1 == check) { perror("pipe"); free(t); return NULL; } t->ls = fd[0]; t->wr = fd[1]; t->enabled = 0; t->exit = 0; t->update = NULL; t->on_time = NULL; check = pthread_create(&(t->thread_id), NULL, main_func, t); if(-1 == check) { perror("pthread_create"); close(fd[0]); close(fd[1]); free(t); return NULL; } return t; }
- 修改set类接口的内存分配逻辑
以timer_set_update_interval为例,先判断指针是否为空,为空则先分配内存再赋值:
void timer_set_update_interval(struct timer *t, int seconds, int microseconds) { if (!t->update_interval) { t->update_interval = malloc(sizeof(struct timeval)); } fill_timeval(t->update_interval, seconds, microseconds); }
timer_set_interval也做相同修改。
- 修改
passed函数的空指针判断
增加对start和interval的空指针校验,避免空指针崩溃:
static int passed(struct timeval *start, struct timeval *interval) { if (!start || !interval) return 0; // 原有逻辑不变 }
修改完成后如果用户没有设置update_interval,会自动使用默认的500ms超时,CPU占用会降到接近0的水平。
其他改进建议
- 修复内存泄漏问题:
timer_stop中将interval置为NULL前要先free原有内存,timer_destroy中要先等待线程退出再释放资源,避免野指针访问 - 补充线程安全校验:
enabled、exit等跨线程访问的变量建议用原子操作或者加互斥锁保护,避免指令重排导致的逻辑异常 - 实现
TIMER_PAUSE功能:当前收到暂停指令无任何处理,可增加剩余时间计算逻辑,恢复时从暂停点继续计时 - 增加参数合法性校验:所有对外接口都增加入参空指针判断,避免用户传参错误导致崩溃
- 优化计时精度:如果是Linux平台可以用
clock_gettime(CLOCK_MONOTONIC, ...)代替gettimeofday,避免系统时间被修改导致的计时异常
内容的提问来源于stack exchange,提问作者Udalny
相关产品推荐
相关产品推荐

