图解:生产者与消费者伪源码模型

Linux TOMORROW 1年前 (2018-07-07) 444次浏览 1个评论 扫描二维码
 西邮 Linux 兴趣小组
 

生产者消费者问题

问题描述:

生产者消费者问题,也称有限缓冲问题,是一个多线程同步问题的经典案例。一起来看看它的实现吧!

图解:生产者与消费者伪源码模型
问题分析

要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。通常采用进程间通信的方法解决该问题。如果解决方法不够完善,则容易出现死锁的情况。出现死锁时,两个线程都会陷入休眠,等待对方唤醒自己。该问题也能被推广到多个生产者消费者的情形。

该问题需要考虑的几点: 

1. 在缓冲区为空时,消费者不能再进行消费 。
       2.在缓冲区为满时,生产者不能再进行生产 。
       3. 在一个线程进行生产或消费时,其余线程不能再进行生产或消费等操作,即保持线程间的同步。 

注意条件变量与互斥锁的顺序。

图解:生产者与消费者伪源码模型
由于前两点原因,因此需要保持线程间的同步,即一个线程消费(或生产)完,其他线程才能进行竞争 CPU,获得消费(或生产)的机会。对于这一点,可以使用条件变量进行线程间的同步:生产者线程在 product 之前,需要 wait 直至获取自己所需的信号量之后,才会进行 product 的操作;同样,对于消费者线程,在 consume 之前需要 wait 直到没有线程在访问共享区(缓冲区),再进行 consume 的操作,之后再解锁并唤醒其他可用阻塞线程。

图解:生产者与消费者伪源码模型
在访问共享区资源时,为避免多个线程同时访问资源造成混乱,需要对共享资源加锁,从而保证某一时刻只有一个线程在访问共享资源。

伪代码实现

相关函数变量名:

1.items 代表缓冲区已经使用的资源数,spaces 代表缓冲区可用资源数。

2.mutex 代表互斥锁。

3.buf[10] 代表缓冲区,其内容类型为 item。

4.in、out 代表第一个资源和最后一个资源。

图解:生产者与消费者伪源码模型
注意事项:

如果将 consumer 的两个 wait 调换,在 producer 发出 signal 信号后,producer 线程再次获得运行机会,执行完了 wait(space),此时,另一个 consumer 线程获得运行机会,执行了 wait(mutex) ,假如这时缓冲区为空,那么 consumer 将会阻塞在 wait(items),而 producer 也会因为无法获得锁的所有权所以阻塞在 wait(mutex),这样两个线程都在阻塞,便会造成死锁。


TOMORROW 星辰 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:图解:生产者与消费者伪源码模型
喜欢 (1)
TOMORROW
关于作者:
一个从石头坑掉到泥坑里的攻城狮。
复杂的朋友发表我的评论  请填写正确的 个人信息
取消评论
表情 加粗 斜体 签到
(1)个小伙伴在吐槽
  1. 好文章!666,学习了
    jxf3382019-05-05 20:17 回复 Windows 7 | 未知浏览器