当前位置:首页 > C > 正文

C语言条件变量详解(多线程同步中的关键工具:pthread_cond_wait 使用教程)

在 C 语言多线程编程中,条件变量(Condition Variable)是一种非常重要的同步机制。它常与互斥锁(mutex)配合使用,用于在线程之间传递“条件已满足”的信号,从而避免忙等待(busy-waiting),提高程序效率。

本教程将带你从零开始,深入浅出地学习 C语言条件变量 的基本概念、工作原理以及实际使用方法,即使你是多线程编程的小白,也能轻松掌握!

C语言条件变量详解(多线程同步中的关键工具:pthread_cond_wait 使用教程) C语言条件变量  pthread_cond_wait 多线程同步 条件变量使用教程 第1张

什么是条件变量?

条件变量是 POSIX 线程(pthread)库提供的一种同步原语,主要用于让一个或多个线程等待某个特定条件变为真。当条件不满足时,线程会进入阻塞状态;当其他线程修改了共享数据并使条件成立后,可以通过发送信号唤醒等待的线程。

核心函数包括:

  • pthread_cond_wait():阻塞当前线程,直到被唤醒。
  • pthread_cond_signal():唤醒一个等待该条件变量的线程。
  • pthread_cond_broadcast():唤醒所有等待该条件变量的线程。

为什么需要条件变量?

假设你有两个线程:一个生产者(Producer)和一个消费者(Consumer)。消费者必须等待生产者准备好数据后才能处理。如果没有条件变量,消费者只能不断轮询检查数据是否就绪,这会浪费大量 CPU 资源。

而使用 条件变量,消费者可以在数据未就绪时“睡着”,直到生产者通知它:“数据好了,可以处理了!” 这就是高效的 多线程同步

条件变量的基本使用步骤

  1. 定义一个 pthread_cond_t 类型的条件变量。
  2. 定义一个 pthread_mutex_t 互斥锁(必须配合使用)。
  3. 在等待线程中:
    • 先加锁(pthread_mutex_lock
    • 检查条件是否满足(通常用 while 循环)
    • 若不满足,调用 pthread_cond_wait(&cond, &mutex)
    • 被唤醒后继续执行,最后解锁
  4. 在通知线程中:
    • 加锁
    • 修改共享数据
    • 调用 pthread_cond_signal()pthread_cond_broadcast()
    • 解锁

完整示例:生产者-消费者模型

下面是一个使用 pthread_cond_wait 实现的简单生产者-消费者程序:

#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <unistd.h>  // for sleep// 全局变量int data_ready = 0;pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t cond = PTHREAD_COND_INITIALIZER;// 消费者线程函数void* consumer(void* arg) {    pthread_mutex_lock(&mutex);        // 使用 while 而不是 if,防止虚假唤醒    while (data_ready == 0) {        printf("消费者:等待数据...\n");        pthread_cond_wait(&cond, &mutex);  // 自动释放 mutex,并阻塞    }        printf("消费者:收到数据!开始处理...\n");    // 处理数据...        pthread_mutex_unlock(&mutex);    return NULL;}// 生产者线程函数void* producer(void* arg) {    sleep(2);  // 模拟耗时操作        pthread_mutex_lock(&mutex);    data_ready = 1;    printf("生产者:数据已准备好!\n");    pthread_cond_signal(&cond);  // 唤醒一个等待线程    pthread_mutex_unlock(&mutex);        return NULL;}int main() {    pthread_t prod_thread, cons_thread;        // 创建线程    pthread_create(&cons_thread, NULL, consumer, NULL);    pthread_create(&prod_thread, NULL, producer, NULL);        // 等待线程结束    pthread_join(cons_thread, NULL);    pthread_join(prod_thread, NULL);        // 销毁条件变量和互斥锁(可选,程序结束前)    pthread_cond_destroy(&cond);    pthread_mutex_destroy(&mutex);        printf("程序结束。\n");    return 0;}  

关键注意事项

  • 必须配合互斥锁使用:条件变量本身不提供互斥,必须与 mutex 一起保护共享数据。
  • 使用 while 循环检查条件:因为存在“虚假唤醒”(spurious wakeup)的可能,不能只用 if 判断。
  • pthread_cond_wait 会自动释放锁:当线程进入等待时,它会原子地释放 mutex 并阻塞;被唤醒后,会重新获取 mutex 再返回。
  • signal 和 broadcast 的区别:前者只唤醒一个线程,后者唤醒所有。根据场景选择。

总结

通过本教程,你已经掌握了 C语言条件变量 的核心用法。它是实现高效 多线程同步 的关键工具,尤其适用于“等待-通知”类场景。记住:pthread_cond_wait 必须与互斥锁配合,并始终在 while 循环中检查条件。

希望这篇 条件变量使用教程 能帮助你写出更安全、高效的多线程 C 程序!