2828

14 分钟

#C 语言标准库函数 cnd_timedwait

/********************************************* * @brief 等待条件变量上收到信号 * @param cond 要等待的条件变量 ID * @param mtx 要解锁的互斥量 ID * @param time_point 超时的时间点 * @return 是否成功 ********************************************/ int cnd_timedwait(cnd_t* restrict cond, mtx_t* restrict mtx, const struct timespec* restrict time_point);

说明

原子地解锁互斥量 mtx 并阻塞当前线程,直到超时或条件变量 cond 上收到 cnd_signalcnd_broadcast 发送的信号时唤醒线程并重新锁定互斥量 mtx

超时时间 time_point 是基于 TIME_UTC 的绝对时间点,而非持续时间。

对于持续时间,需要换算成绝对时间点,例如:

/********************************************* * @brief 生成超时的绝对时间点 * @param[out] time_point 返回绝对时间点 * @param sec 持续的秒数 ********************************************/ void generate_timeout(struct timespec* time_point, int sec) { timespec_get(time_point, TIME_UTC); // 获取基于 TIME_UTC 的当前时间 time_point->tv_sec += sec; // 增加 sec 秒 }

这个函数可能发生虚假的唤醒,即条件变量上并没有收到信号,线程却被唤醒并返回 thrd_success;这是由于内存(缓存)可见性延迟、硬件优化、内存屏障、线程调度、系统信号等原因导致的正常现象。

因此即使返回的是 thrd_success 而非 thrd_timedout,仍应该重新检查条件。

参数

  • cond - 要等待的条件变量 ID
  • mtx - 要解锁的互斥量 ID
  • time_point - 超时的绝对时间点

返回值

  • 成功时返回 thrd_success
  • 超时返回 thrd_timedout
  • 其它失败返回 thrd_error

#示例

#include <stdio.h> #include <threads.h> int main(void) { mtx_t mutex; // 互斥量 cnd_t cond; // 条件变量 mtx_init(&mutex, mtx_plain); // 创建互斥量 cnd_init(&cond); // 创建条件变量 // 计算绝对时间点 struct timespec time_point; timespec_get(&time_point, TIME_UTC); // 获取基于 TIME_UTC 的当前时间 time_point.tv_sec += 5; // 增加 5 秒 printf("开始时间: %s", ctime(&(time_t){time(NULL)})); mtx_lock(&mutex); // 加锁 if (cnd_timedwait(&cond, &mutex, &time_point) == thrd_success) { printf("等待信号成功\n"); } else { printf("等待信号失败\n"); } mtx_unlock(&mutex); // 解锁 printf("结束时间: %s", ctime(&(time_t){time(NULL)})); // 清除互斥量和条件变量 mtx_destroy(&mutex); cnd_destroy(&cond); return 0; }

运行结果

开始时间: Mon Aug 25 16:43:23 2025 等待信号失败 结束时间: Mon Aug 25 16:43:28 2025

#推荐阅读

#参考标准

  • C17 standard (ISO/IEC 9899:2018):
    • 7.26.3.5 The cnd_timedwait function (p: 276-277)
  • C11 standard (ISO/IEC 9899:2011):
    • 7.26.3.5 The cnd_timedwait function (p: 379-380)

创建于 2025/8/25

更新于 2025/8/25