生产者与消费者模型 及 条件变量

本文介绍了生产者和消费者模型,强调了在多线程环境下,生产者与消费者之间以及他们各自内部的互斥关系,同时指出解决同步问题的关键在于条件变量。通过条件变量的初始化、销毁、等待和唤醒等操作,确保生产者和消费者按顺序访问临界资源,防止饥饿问题。此外,解释了在pthread_cond_wait中为何需要互斥量,以保证共享变量的访问安全和避免死锁。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

生产者与消费者问题 及 条件变量
什么是生产者和消费者模型

生产者,顾名思义就是生产东西的人,而消费者就消费的人。在系统中,假设有一块内存,生产者要向内存中放数据,而消费者要从内存区域中拿数据。这片内存区域可以被所有的线程访问,所以这片内存区域就是临界资源,而在对临界区的访问时,要保证不会出错,必须每次对临界区的访问是互斥的。所以当有许多生产者消费者时,每次只能有一个生产者放数据,也只能有一个消费者拿数据,也就是说该内存区域每次只能被一个线程访问。因此,生产者与生产者之间存在着互斥的关系,而消费者与消费者之间也是互斥的关系,在消费者和生产者之间也存在互斥的关系。除此之外,生产者和消费者之间还有一种关系,我们讲在该内存区域中,生产者向其中放数据,消费者拿数据。但当消费者把其中的数据拿完之后,消费者可能会不断的获得锁释放锁,造成生产者的饥饿问题,所以必须要保持两者之间的同步,让两者之间要按照特定的顺序访问。

当存放的数据为满时,生产者必须等待到可以有一个位置存放数据。当存放数据的位置为空时,消费者必须等待有一个位置已经有数据。而为了解决这些问题要使用条件
变量。

三种关系

  • 消费者与消费者之间 互斥关系
  • 生产者与生产者之间 互斥关系
  • 生产者与消费者之间 互斥同步关系
条件变量

条件变量是为了解决同步的问题。
加入当生产者因为存放数据的区域已经满了,从而要等待有空位时才开始放,但是生产者并不知道何时有空位,因此必须要被通知,可以放数据。条件变量解决了 让生产消费者进行等待,和被唤醒的机制,以此来实现同步。

条件变量中提供了几个函数来完成这些操作

条件变量的初始化
pthread_cond_init(pthread_cond_t *restrict, const pthread_condattr_t *restrict attr)

cond: 要初始化的条件变量
attr:属性设置为空
条件变量的销毁
pthread_cond_destroy(pthread_cond_t *cond)
等待条件变量的满足
pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex)

cond:在该条件变量上进行等待
mutex:互斥量

条件变量必须要和互斥锁一起使用,当等待条件变量时,必须先要释放锁(否则会导致,其他的线程无法使用锁,造成死锁),等从等待的条件变量返回时,必须要先获得锁。

唤醒等待
int pthread_cond_broadcast(pthread_cond_t *cond)
//唤醒所有在该条件变量下等待的所有线程
int pthread_cond_signal(pthread_cond_t *cond)
//唤醒该条件变量下的一个线程,等待队列中的第一个线程

pthread_cond_t 和 pthread_mutex_t
都在其内部维持了一个等待队列,来存放等待的线程

为什么在pthread_cond_wait中需要互斥量?
  • 一个线程当在条件不满足时,会陷入等待,而条件变量的等待,必须由其他的线程唤醒,否则会无限期的等待下去。而条件状态不会自己变化,必须由其他线程进行改变,从而使条件满足,并唤醒等待线程。而能被多个线程的看到并访问的为共享变量,对于共享变量的访问,我们必须要使用互斥锁来保护其正确性和安全性。

  • 如果解锁和等待不是一个原子的操作,线程可能会在解完锁,将要进行等待的时候被切换下去,从而可能会错过其他线程发送的唤醒信号,导致该线程无限期阻塞。

  • 因为在等待时会先进行解锁,而在被唤醒后会立即获得锁,这些操作都是原子性的操作

一般的使用规范
pthread_mutex_lock(&lock);
while(条件不满足)  //函数可能会调用失败,所以使用while进行二次检测
    pthread_cond_wait(cond , mutex); 
//操作
pthread_mutex_unlock(&lock);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值