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

std::condition_variable::wait_until中system_clock与steady_clock异常行为问询

为何std::condition_variable::wait_until使用steady_clock仍受系统时间影响?

我在C++中使用std::condition_variable::wait_until,分别通过std::chrono::system_clock和std::chrono::steady_clock指定等待截止时间。根据文档描述,steady_clock的等待不应受系统时间变化影响,而system_clock则会受影响。但实际测试中,两种时钟的等待行为都被系统时间修改干扰了。

最小复现代码

#include <iostream>
#include <chrono>
#include <thread>
#include <mutex>
#include <ctime>
#include <sys/time.h>
#include <condition_variable>
#include <atomic>

std::atomic<bool> flag = false;
std::condition_variable cv;


void wait_using_system_clock()
{
    std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
    std::mutex mtx;
    std::unique_lock lock(mtx);
    cv.wait_until(lock, std::chrono::system_clock::now() + std::chrono::seconds(20), [](){return flag.load();});

    std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
    std::cout << "Time difference [using system clock] = " << std::chrono::duration_cast<std::chrono::seconds>(end - begin).count() << "s" << std::endl;
}

void wait_using_steady_clock()
{
    std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
    std::mutex mtx;
    std::unique_lock lock(mtx);
    cv.wait_until(lock, std::chrono::steady_clock::now() + std::chrono::seconds(20), [](){return flag.load();});

    std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
    std::cout << "Time difference [using steady clock] = " << std::chrono::duration_cast<std::chrono::seconds>(end - begin).count() << "s" << std::endl;
}

void set_system_time_forward()
{
    std::this_thread::sleep_for(std::chrono::seconds(2)); // 确保其他线程已进入cv.wait_until
    struct timeval tv;
    gettimeofday(&tv, NULL);
    tv.tv_sec += 15;
    settimeofday(&tv, NULL);
}

int main()
{
    std::thread t1(wait_using_system_clock);
    std::thread t2(wait_using_steady_clock);

    std::thread t3(set_system_time_forward);
    t1.join();
    t2.join();
    t3.join();

    return 0;
}

测试结果

我启动两个线程分别执行两种时钟的等待逻辑,另一个线程在2秒后将系统时间向前调整15秒。预期使用steady_clock的线程会完整等待20秒,但实际两个线程都只等待了约5秒就结束,输出如下:

Time difference [using system clock] = 5s
Time difference [using steady clock] = 5s

原因分析

这是因为标准库的std::condition_variable::wait_until实现依赖于操作系统的底层条件变量机制,多数Unix-like系统(如Linux)的原生条件变量(pthread_cond_t)默认仅支持基于系统实时时钟(CLOCK_REALTIME)的绝对超时,不支持单调时钟(CLOCK_MONOTONIC)。

当你传递steady_clock的时间点给wait_until时,标准库会将这个单调时间点转换为system_clock对应的系统时间,以此适配底层API。一旦系统时间被修改,转换后的截止时间也会同步变化,导致等待提前结束。

解决方案

如果需要实现不受系统时间影响的等待,可以采用以下两种方案:

  • 使用std::condition_variable::wait_for:它接收的是相对时长而非绝对时间点,标准库可直接基于单调时钟计算等待时长,不受系统时间变化干扰。
  • 若使用C++20及以上版本,可使用std::condition_variable_any配合支持单调时钟的等待接口;或者直接调用操作系统原生API(如Linux下用pthread_condattr_setclock将条件变量的时钟设置为CLOCK_MONOTONIC)。

内容的提问来源于stack exchange,提问作者Techie Fort

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 14:05:11