跳转到主内容
极星编程网:以代码为星,赴技术山海!

c++ 定时器实现方法 c++如何实现一个高精度定时器

std::chrono+std::thread休眠适合毫秒级轻量定时任务,但受调度影响存在抖动;std::jthread+stop_token可安全终止;Windows用CreateWaitableTimerA、Linux用timerfd_create实现高精度,但需注意系统限制与偏差补偿。 std::chrono + std::thread 循环休眠适合轻量级定时任务 精度在毫秒级、对时序抖动不敏感的场景(比如心跳上报、状态轮询),用
std::this_thread::sleep_for
配合
std::chrono
最直接。它不依赖系统底层定时器,可移植性好,但本质是“忙等+休眠”,实际间隔受线程调度影响。 别用
std::this_thread::sleep_until
做长周期定时——如果系统时间被手动调整,可能跳过一次触发 每次休眠前要重新计算下一次目标时间点,避免累积误差;示例中常见错误是写成固定步长
sleep_for(100ms)
,跑久了会漂移 Windows 上
sleep_for(1ms)
实际可能延迟 15ms,Linux 默认调度周期也常为 10ms;真要压到 1ms 以下,得调高线程优先级或改用
clock_nanosleep
std::jthread + stop_token 可安全终止定时循环 C++20 的
std::jthread
自带协作式中断能力,比裸
std::thread
+ 原子标志位更可靠。尤其当你需要在程序退出或配置变更时立刻停掉定时器,它能避免竞态和资源泄漏。 必须在循环内定期检查
stop_token::stop_requested()
,否则
request_stop()
不生效 不要在
stop_callback
里做耗时操作(如锁全局资源、发网络请求),它运行在调用
request_stop()
的线程上下文中 示例代码中容易漏掉
join()
或
detach()
——
std::jthread
析构时自动
join()
,但若你提前 move 出去,就得自己管 Windows 下用 CreateWaitableTimerA 实现 sub-ms 精度 需要微秒级响应(比如音频同步、硬件采样触发),Windows 原生 API 比标准库更靠谱。
CreateWaitableTimerA
配合
SetWaitableTimer
能做到理论 100ns 分辨率,实际受 DPC 延迟和电源策略限制。 必须用
TIMECAPS
查询系统支持的最小精度,
timeGetDevCaps
返回的
wPeriodMin
才是真实下限(常为 1ms) 设置
dwPeriod > 0
启用周期模式,但首次触发仍需手动
SetWaitableTimer
;漏掉这一步会导致只触发一次 回调函数不能是普通成员函数——得用静态函数或 lambda +
std::bind
绑定 this,且必须确保对象生命周期长于定时器 Linux 下 timerfd_create 是最干净的 POSIX 方案
timerfd_create
把定时器封装成文件描述符,可直接塞进 epoll/kqueue,避免额外线程和唤醒开销。适合嵌入事件驱动框架(如 libuv、asio),也方便做多定时器统一管理。 C知道 CSDN推出的一款AI技术问答工具 下载 立即学习 “ C++免费学习笔记(深入) ”; 创建后必须用
timerfd_settime
启动,否则读
timerfd
会永远阻塞;
it_value
设为 0 表示“不启动”,不是“立即触发” 读取返回的是
uint64_t
类型的超时次数,不是时间戳——多次未读会累积,容易误判为“卡顿” 记得设
TFD_CLOEXEC
标志,否则 fork 后子进程会继承该 fd,导致定时器意外触发 高精度不等于高稳定性。哪怕用了
timerfd
或
CreateWaitableTimer
,如果线程被抢占、CPU 频率动态缩放、或系统启用了节能模式,实测抖动仍可能翻倍。真正关键的定时逻辑,得配合硬件时间戳(如
RDTSC
)做偏差补偿,而不是只靠 API 声称的精度。

相关文章