3208

16 分钟

#C 语言标准库函数 cnd_init

/********************************************* * @brief 创建条件变量 * @param[out] cond 返回条件变量 ID * @return 是否成功 ********************************************/ int cnd_init(cnd_t* cond);

说明

创建一个条件变量,通过参数 cond 返回条件变量 ID。

不再使用时需要通过 cnd_destroy 函数清理条件变量。

条件变量能够原子地解锁互斥量并阻塞当前线程,从而高效地进入等待;当条件变量收到信号时,线程被唤醒并再次锁定互斥量。

参数

  • cond - 返回条件变量 ID

返回值

  • 成功时返回 thrd_success
  • 内存不足时返回 thrd_nomem
  • 其它失败返回 thrd_error

#示例

#include <stdio.h> #include <threads.h> // 全局变量 mtx_t mutex; // 互斥量 cnd_t cond; // 条件变量 int turn = 1; // 1 表示线程 1 打印,2 表示线程 2 打印 // 线程函数1 int func1(void* data) { // 与线程 2 交替打印 for (int i = 0; i < 10; i++) { mtx_lock(&mutex); // 锁定互斥量 while (turn != 1) { cnd_wait(&cond, &mutex); // 等待信号 } printf("线程1: %d\n", i); turn = 2; cnd_signal(&cond); // 发送信号,唤醒线程 2 mtx_unlock(&mutex); // 解锁互斥量 } return 0; } // 线程函数2 int func2(void* data) { // 与线程 1 交替打印 for (int i = 0; i < 10; i++) { mtx_lock(&mutex); // 锁定互斥量 while (turn != 2) { cnd_wait(&cond, &mutex); // 等待信号 } printf("线程2: %d\n", i); turn = 1; cnd_signal(&cond); // 发送信号,唤醒线程 1 mtx_unlock(&mutex); // 解锁互斥量 } return 0; } int main(void) { mtx_init(&mutex, mtx_plain); // 创建互斥量 cnd_init(&cond); // 创建条件变量 // 创建线程 thrd_t th1, th2; thrd_create(&th1, func1, NULL); thrd_create(&th2, func2, NULL); // 等待线程结束 thrd_join(th1, NULL); thrd_join(th2, NULL); // 清除互斥量和条件变量 mtx_destroy(&mutex); cnd_destroy(&cond); return 0; }

运行结果

线程1: 0 线程2: 0 线程1: 1 线程2: 1 线程1: 2 线程2: 2 线程1: 3 线程2: 3 线程1: 4 线程2: 4 线程1: 5 线程2: 5 线程1: 6 线程2: 6 线程1: 7 线程2: 7 线程1: 8 线程2: 8 线程1: 9 线程2: 9

说明

这个示例通过条件变量实现两个线程交替打印。

如果不用条件变量,一个线程要等待某个“条件”成立(例如示例中 turn 的值),它只能用轮询的方式:

while (turn != 1) { // 一直检查,CPU空转,浪费资源 }

这会导致 CPU 忙等(busy-waiting),既浪费性能,又不利于调度。

条件变量的出现就是为了解决这个问题:

  • 线程在条件不满足时调用 cnd_wait,解锁互斥量并阻塞当前线程,不消耗 CPU;

  • 当另一个线程改变了条件,它调用 cnd_signalcnd_broadcast 唤醒等待的线程;

  • 被唤醒的线程会再次加锁互斥量,用户应当重新检查条件,如果满足,就继续运行。

#推荐阅读

#参考标准

  • C17 standard (ISO/IEC 9899:2018):
    • 7.26.3.3 The cnd_init function (p: 276)
  • C11 standard (ISO/IEC 9899:2011):
    • 7.26.3.3 The cnd_init function (p: 379)

创建于 2025/8/25

更新于 2025/8/25