生产者-消费者模式的简介:

在实际的软件开发过程中,我们将产生数据的模块称为生产者,处理数据的模块成为消费者。但仅有这两者还不够成为一个生产者-消费者模式,还需要有一个缓冲区(一段内存区域)作为中介,生产者产生的数据放入缓冲区,消费者从缓冲区读取数据并处理。(注:上述所说的模块是广义的,可以是类,函数,线程,进程等)

我们可以将这二者之间的关系图表示出来:

总结:我们用3-2-1的方法来简单描述一个生产者-消费者模式,3代表有三种关系:生产者-生产者,消费者-消费者,生产者-消费者;2代表两个角色:生产者,消费者;1代表一个交易场所:缓冲区

生产者-消费者模式之间的三种关系:

模拟实现生产者-消费者模式之前,我们需要先捋清除这之间的关系:

  • 生产者-生产者:很明显,这两者之间必定是一种竞争关系,也就是说一个生产者往缓冲区放数据时另一个生产者就不能去访问这块空间
  • 消费者-消费者:同样,两个消费者之间也是竞争的关系,这就好比两个人同时看中一件商品时,他们之间就是一种竞争的关系
  • 生产者-消费者:生产者与消费者之间其实是一种同步与互斥的关系,假设只有一个生产者一个消费者时,只有生产者放入数据后消费者才能读取,消费者拿到数据后生产者才去生产,这就是一种同步;但当生产者生产数据的时候消费者就不能从缓冲区拿数据,或者消费者读数据的时候生产者就不能往缓冲区里写数据,否则很可能会导致两者都存/取数据失败,产生二义性问题。

生产者-单消费者的实现:

  • 方案一:使用互斥锁+条件变量
    我们现在模拟一个场景,生产者将生产的数据放入交易场所,消费者从中读取。这个场所我们就用单链表来模拟(它还可以是任意一个数据结构,只要能够存储数据),生产者放入数据时进行头插,消费者消费数据时进行头删(这里我采用的是头插头删的方式,当然也可以用尾插、尾删的方式实现):

既然已经确定了生产场所,其次我们要考虑到如何才能让这二者时间实现同步与互斥。多线程编程中提到了“条件变量(Condition Variable)”,在此,我们再次简单回顾一下这几个函数:(文章链接:http://blog.csdn.net/qq_33951180/article/details/72801651)

//初始化一个条件变量
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);  //销毁一个条件变量
int pthread_cond_destroy(pthread_cond_t *cond);  //唤醒等待的线程
int pthread_cond_signal(pthread_cond_t *cond); //唤醒一个
int pthread_cond_broadcast(pthread_cond_t *cond);  //唤醒所有//阻塞等待
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
//设定超时等待
int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,  const struct timespec *restrict abstime);  

我们可以利用条件变量中的相关函数来模拟实现,当生产者线程生产数据时消费者线程就wait,当消费者被唤醒后,此时链表已经有数据(消费者等待成功),拿走结点;消费者读取数据的过程中生产者在wait,等到消费者读取数据完之后被唤醒,然后继续往缓冲区写入数据(循环………),等待与被唤醒的过程就可以利用上述的pthread_cond_wait和pthread_cond_signal函数实现。

代码以托管到github:
https://github.com/lybb/Linux/tree/master/Product_Consumer/product_consumer_2_19

  • 方案二:使用信号量实现
    我们将方案一中的链表这次该为环形队列,环形队列使用数组模拟实现(循环链表也可以),如图:

我们将数组想象成上图中的环形队列,生产者和消费者都从0号下标的位置开始走,一开始,环形队列中有N个空格子和0个数据,因此,在生产者没有生产数据之前,消费者是不能进行消费的;
当生产者生产的数据占满整个环形buf时,假设消费者还在0号位置,生产者和消费者就会再次在0号位置相遇,此时有0个block资源和N个data资源,因此生产不能继续放入数据;
当消费者和生产者都在执行时,一旦消费者追上了生产者,消费者就没有资源可供使用了。

综上:使用环形buf的情况下,生产者和消费者必须满足:
①一开始,必须保证生产者先运行;
②生产者不能将消费者套圈(参考上述第二点);
③消费者不能追上生产者(参考第三点)

对于生产者来说:只关心空格子(block)资源
对于消费者来说:只关心数据(data)资源

因此,我们在用信号量实现时,需要两个信号量来分别表示block和data资源。

代码上传至github:
https://github.com/lybb/Linux/tree/master/Product_Consumer/Ring

  • 两种实现方案的比较:
    互斥锁+条件变量实现的是有锁同步,而信号量实现的是无锁同步

多线程实现生产者与消费者模式相关推荐

  1. 多线程通信—生产者和消费者模式

    1.队列Queue: 从一个线程向另一个线程发送数据最安全的方式可能就是使用queue库中的队列了.创建一个被多个线程共享的Queue对象,这些线程通过使用put()和get()操作来向队列中添加或者 ...

  2. Java并发编程系列18:多线程之生产者和消费者模式_信号灯法(wait/notify通知机制)

    1.生产者消费者模式 生产者消费者问题(Producer-consumer problem),也称为有限缓冲问题(Bounded-buffer problem),是一个多线程同步问题的经典案例.该问题 ...

  3. python 生产者和消费者模式_Python爬虫:生产者和消费者模式

    认识生产者和消费者模式 生产者和消费者是多线程中很常见的一个问题.产生数据的模块,我们称之为生产者,而处理数据的模块,就称为消费者.但是单单只有生产者和消费者显然还是不够的,一般来说,我们还有一个缓冲 ...

  4. 认识生产者和消费者模式

    认识生产者和消费者模式 生产者和消费者是多线程中很常见的一个问题.产生数据的模块儿,我们称之为生产者,而处理数据的模块,就称为消费者.但是单单只有生产者和消费者显然还是不够的,一般来说,我们还有一个缓 ...

  5. python 多线程并发编程(生产者、消费者模式),边读图像,边处理图像,处理完后保存图像实现提高处理效率

    文章目录 需求 实现 先导入本次需要用到的包 一些辅助函数 如下函数是得到指定后缀的文件 如下的函数一个是读图像,一个是把RGB转成BGR 下面是主要的几个处理函数 在上面几个函数构建对应的处理函数 ...

  6. Java基础进阶多线程-生产者和消费者模式

    1.什么是"生产者和消费者模式"? 生产线程负责生产,消费线程负责消费 生产线程和消费线程要达到均衡 这是一种特殊的业务需求,在这种特殊的情况下需要使用wait方法和notify方 ...

  7. Python中的生产者与消费者模式(转载)

    利用多线程和队列可以实现生产者消费者模式.该模式通过平衡生产线程和消费线程的工作能力来提高程序整体处理数据的速度. 1.什么是生产者和消费者? 在线程世界里,生产者就是生产数据(或者说发布任务)的线程 ...

  8. Java多线模式-Producer-Consumer模式(生产者、消费者模式)

    1.场景 有些时候需要两个或两个以上的线程协同工作,每个线程需要使用其他线程产生数据. 2.详细说明 可以把上面的场景抽象成生产者和消费者模式.从消费者的角度:消费者需要消费生产者生成的产品. 从生产 ...

  9. 线程间的协作(2)——生产者与消费者模式

    2019独角兽企业重金招聘Python工程师标准>>> 1.何为生产者与消费者 在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程. import java.util. ...

最新文章

  1. 几条跟堆栈扯上关系的汇编指令
  2. Mathtype写分段函数的方法
  3. Unix中的I/O模型和Java NIO
  4. 域名防系统+独立接口池+独立会员+独立权限
  5. python的类里的属性是否可以为列表_是否有Python方法可以访问类的所有非私有和非内置属性?...
  6. linux开机自启动python脚本_Linux下Python脚本自启动和定时启动的详细步骤
  7. python-docx-template 数据渲染_python如何将数据渲染到docx文档指定位置
  8. log4j不生成日志文件的问题
  9. Linux LVM动态扩容
  10. sql查询表名、列名、列属性
  11. python如何做一个财务报表_用python帮财务小姐姐自动生成财务报表
  12. 解决:windows电脑连接iphone手机热点,iphone锁屏后热点会自动断开
  13. 什么是 BigMap 算法
  14. win10怎样获得计算机管理员权限,详细教你获取win10管理员权限
  15. 小米手机访问电脑共享文件_小米手机不用数据线直接访问电脑上的文件的方法...
  16. php 在对象中递归 坑,PHP_PHP对象递归引用造成内存泄漏分析,通常来说,如果PHP对象存在递 - phpStudy...
  17. 8. 【gRPC系列学习】resetTransport建立TCP连接流程
  18. 食品保质期提醒应用 android,保质期提醒app
  19. windows软件常用快捷键cmd+英文写作工具推荐
  20. 这个 拿去 用 这70个让你笑的合不拢嘴的GitHub项目,居然拿了7万星

热门文章

  1. [AP]无线AP和无线路由的区别
  2. CSS------美化网页
  3. GOF23设计模式-创建型模式4-原型模式
  4. LCD段码液晶屏PIN脚间距
  5. UI设计电脑配置要求,UI设计笔记本可以吗?
  6. 量化交易是什么意思?怎么理解?
  7. 微前端之 qiankun 入门、上手、实战(构建大型 web 应用)
  8. linux进程系列(5)进程链与进程扇
  9. Java实现简单的倒排索引
  10. TotalCommander 之 快捷键