概述
 
         与互斥锁不同,条件变量是用来等待而不是用来上锁的。条件变量用来自动阻塞一个线程,直到某特殊情况发生为止。通常条件变量和互斥锁同时使用 
 。  
 
 
         条件变量使我们可以睡眠等待某种条件出现。条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:  
 
 
         1.一个线程等待"条件变量的条件成立"而挂起;  
 
 
         2.另一个线程使 “条件成立”(给出条件成立信号)  
 
 
         想象一种情况,我创建一个线程去执行下雨收衣服的工作,但是大多数时候天气都是晴天,只有下雨天这个线程才会去工作,那么我就需要这个线程睡眠,不要浪费CPU 资源,等下雨时我再叫醒它起来工作就行了,线程条件变量就是扮演这样一个角色。  
 
 
         条件的检测是在互斥锁的保护下进行的。线程在改变条件状态之前必须首先锁住互斥量。如果一个条件为假,一个线程自动阻塞,并释放等待状态改变的互斥锁。如果另一个线程改变了条件,它发信号给关联的条件变量,唤醒一个或多个等待它的线程,重新获得互斥锁,重新评价条件。如果两进程共享可读写的内存,条件变量 可以被用来实现这两进程间的线程同步。  
 
 
         在 linux 的 pthread 中使用条件变量的类型为:pthread_cond_t 表示一个条件变量 
 
typedef union{struct __pthread_mutex_s __data ;char __size [ __SIZEOF_PTHREAD_MUTEX_T ];long int __align ;} pthread_mutex_t ;
 
 对线程条件变量的操作可以有 
 
 
  1.初始化条件变量  
 
 
  
  2.销毁条件变量  
 
 
  
  3.等待条件变量(线程睡眠)  
 
 
  
  4.唤醒等待条件变量的线程 
 
 
初始化条件变量
动态初始化(pthread_cond_init)
 
  头文件:  
 
 
 #include <pthread.h> 
  函数原型:  
  
 
 int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr); 
  作用:  
 
 
  
          初始化线程条件变量 cond  
 
 
  
  参数含义:  
 
 
  
          cond:线程条件变量  
 
 
  
          attr:线程条件变量的属性,为空表示默认属性  
 
 
  
  返回值:  
 
 
  
          成功返回 0,  
 
 
  
          失败返回错误号  
 
 
静态初始化
 
  在 linux 中使用静态存储区中的  
  PTHREAD_COND_INITIALIZER  
  就可以对条件变量完成静  
 
 
  
  态初始化  
 
 
 /* Conditional variable handling. */#define PTHREAD_COND_INITIALIZER { { { 0 }, { 0 }, { 0 , 0 }, { 0 , 0 }, 0 , 0 , { 0 , 0 } } }
 
  如下:  
 
 
 pthread_cond_t cond = PTHREAD_COND_INITIALIZER;销毁条件变量(pthread_cond_destroy)
 
  头文件:  
 
 
 #include <pthread.h> 
  函数原型:  
 
 
 int pthread_cond_destroy(pthread_cond_t *cond); 
  作用:  
 
 
  
          销毁线程条件变量 cond  
 
 
  
  参数含义: 
 
 
  
           
  cond: 
  线程条件变量  
 
 
  
  返回值:  
 
 
  
          成功返回 0,  
 
 
  
          失败返回错误号 
 
 
等待一个条件变量(线程睡眠)
阻塞等待(pthread_cond_wait)
 
  头文件:  
 
 
 #include <pthread.h> 
  函数原型:  
  
 
 int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex); 
  作用:  
 
 
  
          阻塞等待条件变量 cond  
  的值,线程进入睡眠状态并解锁,直到被条件变量唤醒  
 
 
  
  参数含义:  
 
 
  
          cond:线程条件变量  
 
 
  
          mutex:互斥锁  
 
 
  
  返回值:  
 
 
  
          成功返回 0,  
 
 
  
          失败返回错误号  
 
 
  
  备注:  
 
 
  
          1.因为条件变量本身是一个“共享资源”,为了避免竞争,需要一个线程互斥锁来保护 
  它  
 
 
  
          2.在 pthread_cond_wait/pthread_cond_timewait 需要把锁住的互斥锁传入函数,在函数内部实现的时候,线程让出 CPU(休眠)前,释放传入的互斥锁,然后再休眠  
 
 
  
          3.休眠到直到条件发生(被唤醒),被唤醒的时候,再次重新锁住传入的锁(不会带锁休眠),也就是说线程在睡眠的时候会解锁,在被唤醒时会去获取锁 
 
 
限时等待(pthread_cond_timedwait)
 
  头文件:  
 
 
 #include <pthread.h>函数原型:
int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,const struct timespec *restrict abstime); 
  作用:  
 
 
  
          限时等待条件变量 cond  
  的值,线程进入睡眠状态并解锁,直到被条件变量唤醒或到达绝对时间 abstime  
 
 
  
  参数含义:  
 
 
  
          cond:线程条件变量  
 
 
  
          mutex:互斥锁  
 
 
  
          abstime: 是一个绝对时间(当前时间+等待时间),表示超过这个时间将直接返回  
 
 
  
  返回值:  
 
 
  
          成功返回 0,  
 
 
  
          失败返回错误号 
 
 
唤醒等待条件变量的线程
唤醒所有等待该条件变量的线程(pthread_cond_broadcast)
 
  头文件:  
 
 
 #include <pthread.h> 
  函数原型:  
 
 
 int pthread_cond_broadcast(pthread_cond_t *cond); 
  作用:  
 
 
  
          唤醒所有等待条件变量 cond  
  的线程  
 
 
  
  参数含义:  
 
 
  
          cond:线程条件变量  
 
 
  
  返回值:  
 
 
  
          成功返回 0,  
 
 
  
          失败返回错误号 
 
 
唤醒一个等待该条件变量的线程(pthread_cond_signal)
 
 头文件:  
 
#include <pthread.h> 
 函数原型:  
 
 
int pthread_cond_signal(pthread_cond_t *cond); 
 作用:  
 
 
         激活一个等待该条件 cond  
 的线程,存在多个等待线程时按入队顺序激活其中一个;  
 
 
 参数含义:  
 
 
         cond:线程条件变量  
 
 
 返回值:  
 
 
         成功返回 0,  
 
 
         失败返回错误号  
 
 
 备注:  
 
 
         在生产者消费者模型中,如果生产者一次性可以产出多个任务,那么用 
 pthread_cond_broadcast 好一点,如果溢出只产生一个任务,那么使用pthread_cond_signal 好一点 
 
使用示例
#include <stdio.h>
#include <pthread.h>
static pthread_t thread1;
static pthread_t thread2;
//静态初始化
static pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
void *function1()
{
    while(1)
    {
        pthread_mutex_lock(&lock);
        printf("===== 线程 1 进入睡眠 ====\n");
        pthread_cond_wait(&cond,&lock);
        printf("==== 线程 1 唤醒 ====\n");
        pthread_mutex_unlock(&lock);
    }
}
void *function2()
{
    while(1)
    {
        pthread_mutex_lock(&lock);
        printf("===== 线程 2 进入睡眠 ====\n");
        pthread_cond_wait(&cond,&lock);
        printf("==== 线程 2 唤醒 ====\n");
        pthread_mutex_unlock(&lock);
    }
}
int main()
{
    int i=0;
    if(-1==pthread_create(&thread1,NULL,function1,NULL))
    {
        printf("thread_create1 fail!\n");
        pthread_detach(thread1);
    }
    if(-1==pthread_create(&thread2,NULL,function2,NULL))
    {
        printf("thread_create fail!\n");
        pthread_detach(thread1);
    }
    while(1)
    {
        sleep(2);
        i++;
        printf("\n 第%d 次唤醒\n",i);
        pthread_mutex_lock(&lock);
        if(-1==pthread_cond_signal(&cond))
        {
            printf("pthread_cond_broadcast error!\n");
        }
        pthread_mutex_unlock(&lock);
    }
    return 0;
}










![[Linux入门]---搭建Linux环境](https://img-blog.csdnimg.cn/f939d4c14a184fc0b1a615cb1fe119f4.png)







