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
相关产品推荐
相关产品推荐

