std::chrono::steady_clock 是唯一靠谱的选择,因其单调递增、不受系统时间调整影响,适合倒计时和超时判断;high_resolution_clock 不可靠,可能退化为 system_clock;sleep_until 比 sleep_for 更精准,但唤醒后仍需校验时间。

std::chrono::steady_clock 是唯一靠谱的选择
闹钟不准,十有八九是因为用了 system_clock。它受系统时间调整影响——比如 NTP 同步、手动改时间,system_clock::now() 可能突然跳变,导致定时提前或卡死。而 steady_clock 是单调递增的,不随系统时间漂移,适合做倒计时和超时判断。
- 用
steady_clock获取起始点和当前点,差值才是真实经过时间 - 不要用
system_clock做相对等待,哪怕只是“5秒后触发” - Windows 上
steady_clock底层是QueryPerformanceCounter,Linux 是CLOCK_MONOTONIC,都满足高精度(通常纳秒级,实际分辨率看硬件)
auto start = std::chrono::steady_clock::now(); // ... 工作 ... auto elapsed = std::chrono::steady_clock::now() - start; auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count();
wait_until 比 sleep_for 更可靠
想“等到某个绝对时刻再执行”,别用循环 + sleep_for,容易因调度延迟错过目标时间。直接用 condition_variable::wait_until 或 std::this_thread::sleep_until,它们内部会处理唤醒时机,精度更高。
-
sleep_until在目标时间前被唤醒是允许的(比如线程被中断),但不会晚于目标时间 - 如果需要严格保证“不早于”,得在唤醒后手动检查是否真到了时间点,再补等
- 多线程环境下,
wait_until配合condition_variable更适合带条件的闹钟(如“等某标志置位或超时”)
auto wake_time = std::chrono::steady_clock::now() + std::chrono::seconds(10); std::this_thread::sleep_until(wake_time); // 此刻大概率已到 wake_time,但不保证绝对精确,建议再 check 一次
精度陷阱:std::chrono::high_resolution_clock 不等于高精度
很多人看到名字就以为 high_resolution_clock 最准,其实它只是别名——在 GCC 和 MSVC 上,它通常就是 steady_clock;但在某些旧平台或编译器配置下,它可能退化为 system_clock。依赖它写闹钟,等于埋雷。
- 直接用
steady_clock,语义明确,行为稳定 - 不要假设
high_resolution_clock::period::den大就一定准,最终精度取决于 OS 调度粒度(Windows 默认 15ms,可调但有代价) - 实测发现,即使底层支持微秒级,用户态线程也很难稳定做到 ±100μs 内唤醒,别对 sub-millisecond 闹钟抱幻想
跨平台休眠唤醒抖动大?加个 busy-wait 收尾
操作系统睡眠唤醒本身有不可控延迟(尤其负载高时),sleep_until 返回后,离目标时间可能还差零点几毫秒。如果业务对误差敏感(比如音频同步、高频控制),可以在接近目标时切为短间隔轮询。
立即学习“C++免费学习笔记(深入)”;
- 先用
sleep_until睡到距离目标 1ms 内 - 再用
while (steady_clock::now() 补齐 - 注意别空转太久,yield 比裸循环友好,但仍有 CPU 占用;1ms 是经验值,太小没意义,太大又失去意义
真正的难点不在 clock 选哪个,而在于你能否接受“唤醒时刻由 OS 决定”这个事实。用户态代码永远没法绕过调度器,所有“高精度”都是在容忍范围内尽力逼近。










