Linux Pthread 条件变量

阅读了《Unix/Linux系统编程》一书中关于Pthread中的条件变量相关内容,进行了整理总结
本文包含了临界区、条件变量等内容,并关于pthread_cond_wait放在while还是if中通过示例进行了具体分析
参考资料

5. 条件变量

条件变量是用来等待线程而不是上锁的,条件变量通常和互斥锁一起使用。条件变量之所以要和互斥锁一起使用,主要是因为互斥锁的一个明显的特点就是它只有两种状态:锁定和非锁定,而条件变量可以通过允许线程阻塞和等待另一个线程发送信号来弥补互斥锁的不足,即提供了一种线程协作的方式。

5.1 条件变量初始化

Pthreads中pthread_cond_t即为条件变量类型,与互斥量方法一样,条件变量有两种初始化方法。

  • 静态方法:定义一个条件变量con,并使用默认属性对其进行初始化

    pthread_cond_t con = PTHREAD_COND_INITIALIZER;
    
  • 动态方法:使用pthread_cond_init()函数来初始化条件变量,通过第二个参数设置条件变量属性。第二个参数可以设置为NULL来使用默认属性初始化条件变量

    int pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t *attr)
    
    pthread_cond_init(&con,NULL);
    

5.2 条件变量使用:

  • 等待条件变量函数:pthread_cond_wait

    int pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex)
    

    当线程调用pthread_cond_wait()函数时,该函数会阻塞调用线程,直到发出指定条件的信号。会将调用线程放到等待条件的线程列表上,并对互斥量解锁(这样就不会死锁)。当pthread_cond_wait()返回时(即收到信号后),互斥量再次锁住

    因为要根据共享变量的状态来决定是否等待(即互斥的访问共享变量),因此在该函数调用前要先获取相关互斥量(即正在互斥的访问该共享变量)。所以该函数必须要放在pthread_mutex_lockpthread_mutex_unlock之间的临界区内。

    该函数放在if还是while里面:

    需要注意由于有可能同时唤醒多个正在等待该条件的线程。因此,如果pthread_cond_wait放在if里面而不是while里面,那么当被唤起两个线程时(考虑争夺仅有的一个资源时的情况),会发生第二个线程没有资源可以消费的情况,后续操作出现错误!因此,一定要使用while做进一步循环判断,这样即使两个线程都被唤起,那么第二个线程会再次判断资源是否可用,如果不可用,就再次pthread_cond_wait。如

    while(resource == FALSE)
          pthread_cond_wait(&cond, &mutex)
    

    这个例子将放在本节第二个示例中具体分析

  • 通知线程条件满足:pthread_cond_signalpthread_cond_broadcast

    int pthread_cond_signal(pthread_cond_t * cond)
    

    该函数发出信号唤醒至少一个正在等待该条件的线程

    pthread_cond_signal既可以放在pthread_mutex_lockpthread_mutex_unlock之间**(推荐)**,也可以放在pthread_mutex_lockpthread_mutex_unlock之后,但是各有各的缺点。推荐使用第一种

    int pthread_cond_broadcast(pthread_cond_t * cond)
    

    该函数会唤醒等待该条件的所有线程

5.3 条件变量使用示例:简单(单一)生产者消费者问题

定义一个int类型全局变量num,并指定其上限。生产者线程不停往里面+1直到加到上限,然后就不能加了,要等消费者减后才能继续加;消费者线程不停往里面-1直到减到0,然后就不能减了,要等生产者加后才能继续减

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>

#define MAX 5//共享变量最大值上界
int num;//全局共享变量

pthread_mutex_t * m;//互斥量
pthread_cond_t * push;//条件变量push:表示生产者生产了一个产品
pthread_cond_t * pop;//条件变量pop:表示消费者消费了一个产品

//消费者线程入口函数
void* consumer(void*arg){
   
    for(int i = 0 ; i < 15 ; ++i){
   
        pthread_mutex_lock(m);//上锁
        if(num == 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值