C语言条件变量

1.简介

条件变量是一种线程同步机制,其核心作用是允许线程在特定条件未满足时进入休眠状态, 并在条件满足时被其他线程唤醒继续执行,通过“等待-通知”模式实现线程间的协调, 避免了忙等待(即不断轮询检查条件)带来的资源浪费,从而提高程序效率。 基于linux环境下或者windows的mingw环境(posix接口)。

2.条件变量时间轴分析

我们主要分析pthread_cond_wait()的使用

2.1 消费者线程示例

先以示例代码进行展示,使用方式

pthread_mutex_lock(&mutex);        // [1] 消费者加锁成功
while (queue_empty) {
    printf("准备进入wait...当前锁状态: 已锁定\n");

    pthread_cond_wait(&cond, &mutex);  // [2] 这个函数内部:
                                       //     - 先解锁mutex
                                       //     - 然后线程挂起等待
                                       //     - 等待期间mutex是解锁状态!
                                       //     - 被唤醒后,在返回前重新加锁

    printf("从wait返回...当前锁状态: 已重新锁定\n");
}
// 消费数据...
pthread_mutex_unlock(&mutex);      // [3] 消费者解锁

2.2 条件变量等待过程的时间线

pthread_cond_wait的时间流程,以及这个过程中,锁的状态。

//-----------------------------------时间线------------------
时间点  |       消费者线程      |消费者的锁状态   |   生产者线程
t1      pthread_mutex_lock()    锁定            可能被阻塞在pthread_mutex_lock()
t2      进入while(queue_empty)  锁定            同上
t3      调用pthread_cond_wait() 锁定->解锁
t4      --第一步,解锁           解锁
t5      --第二步,线程等待挂起    解锁
t6                              解锁            pthread_mutex_lock()---成功,可以进行生成操作
t7                              解锁            生产者,修改,正常生成,queue_empty=false
t8                              解锁            生成完成,调用pthread_cond_signal() ,唤醒消费者
t9      消费者被唤醒             解锁
t10     pthread_cond_wait()内部 解锁->锁定
t11     --重新加锁              锁定            pthread_mutex_unlock(),生产者解锁
t12     pthread_cond_wait()返回 锁定
t13     消费数据。。。。            锁定
t14     pthread_mutex_unlock()  解锁

2.3 条件变量通知

上面讲的是条件变量pthread_cond_wait里面的锁的状态,现在在说条件变量的通知机制 pthread_cond_signal、pthread_cond_boardcast不同的系统上有不同的实现, 底层上pthread_cond_wait机制中,线程被加入到等待队列,然后进入内核态的等待状态,在 Linux 内核中, 实际的唤醒是通过 futex(Fast Userspace muTEX)系统调用。

  • pthread_cond_signal
  1. 从等待队列中选择一个线程(通常是 FIFO)
  2. 通过 futex 系统调用唤醒该线程
  3. 只进行一次唤醒操作
  • pthread_cond_broadcast
  1. 遍历整个等待队列
  2. 唤醒所有等待线程(或使用 INT_MAX 参数)
  3. 清空等待队列