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