You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

修复方案

  1. 修改定时器创建逻辑,合理初始化指针
    将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;
}
  1. 修改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也做相同修改。

  1. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 01:48:02