架构设计:生产者/消费者模式:双缓冲区 - 包蒙吉 - IT人社区 - powered by italent.cc

来源:百度文库 编辑:神马文学网 时间:2024/04/19 19:07:46

架构设计:生产者/消费者模式:双缓冲区


“双缓冲区”是一个应用很广的手法。该手法用得最多的地方想必是屏幕绘制相关的领域(主要是为了减少屏幕闪烁)。另外,在设备驱动和工控方面,双缓冲也经常被使用。不过今天要聊的,并不是针对上述的某个具体领域,而是侧重于并发方面的同步/互斥开销。

  ★为啥要双缓冲区
  记得前几天在介绍队列缓冲区时,提及了普通队列缓冲区的两个性能问题:“内存分配的开销”和“同步/互斥的开销”(健忘的同学,先回去看看那个帖子复习一下)。“内存分配的开销”已经在介绍环形缓冲区的时候解决了,而今天要介绍的双缓冲区,就是冲着同步/互斥的开销来的。
  为了防止有人给咱扣上“过度设计”的大帽子,又得来一个事先声明:只有当同步或互斥的开销非常明显的时候,你才应该考虑双缓冲区的使用。否则的话,大伙儿还是老老实实用最基本、最简单的队列缓冲区吧。

  ★双缓冲区的原理
  前面说了一通废话,现在开始切入正题,说说具体实现。
  所谓“双缓冲区”,故名思义就是要有俩缓冲区(简称A和B)。这俩缓冲区,总是一个用于生产者,另一个用于消费者。当俩缓冲区都操作完,再进行一次切换(先前被生产者写入的转为消费者读出,先前消费者读取的转为生产者写入)。由于生产者和消费者不会同时操作同一个缓冲区(不发生冲突),所以就不需要在读写每一个数据单元的时候都进行同步/互斥操作。顺便提一下,这又一次展现了空间换时间的优化思路。
  但是光有俩缓冲区还不够。为了做到“不冲突”,还得再搞两个互斥锁(简称La和Lb),分别对应俩缓冲区。生产者或消费者如果要操作某个缓冲区,必须先拥有对应的互斥锁。补充一句:要达到“不冲突”的效果,其实可以有多种搞法,今天只是挑一个简单的来聊。

  ★双缓冲区的几种状态
  为了加深某些同学的理解,再描述一下双缓冲区的几种状态。
  ◇俩缓冲区都在使用的状态(并发读写)
  大多数情况下,生产者和消费者都处于并发读写状态。不妨设生产者写入A,消费者读取B。在这种状态下,生产者拥有锁La;同样的,消费者拥有锁Lb。由于俩缓冲区都是处于独占状态,因此每次读写缓冲区中的元素(数据单元)都不需要再进行加锁、解锁操作。这是节约开销的主要来源。
  ◇单个缓冲区空闲的状态
  由于两个并发实体的速度会有差异,必然会出现一个缓冲区已经操作完,而另一个尚未操作完。不妨假设生产者快于消费者。
  在这种情况下,当生产者把A写满的时候,生产者要先释放La(表示它已经不再操作A),然后尝试获取Lb。由于B还没有被读空,Lb还被消费者持有,所以生产者进入发呆(Suspend)状态。
  ◇缓冲区的切换
  接着上面的话题。
过了若干时间,消费者终于把B读完。这时候,消费者也要先释放Lb,然后尝试获取La。由于La刚才已经被生产者释放,所以消费者能立即拥有La并开始读取A的数据。而由于Lb被消费者释放,所以刚才发呆的生产者会缓过神来(Resume)并拥有Lb,然后生产者继续往B写入数据。
  经过上述几个步骤,俩缓冲区完成了对调,变为:生产者写入B,消费者读取A。

  ★可能的并发问题
  本来单个缓冲区的生产者/消费者问题就已经是教科书的经典问题了,现在搞出俩缓冲区,所以就更加耗费脑细胞了。一不小心,就会搞出些并发的Bug,而且并发的Bug还很难调试和测试(这也就是为啥不要轻易使用该玩意儿的原因)。
  ◇死锁的问题
  假如把前面介绍的操作步骤调换一下顺序:生产者或消费者在操作完当前的缓冲区之后,先去获取另一个缓冲区的锁,再来释放当前缓冲区的锁。那会咋样捏?
  一旦两个并发实体同时处理完各自缓冲区,然后同时去获取对方拥有的锁,那就会出现典型的死锁(死锁的详细解释参见“这里”)场景。它俩从此陷入万劫不复的境地。

  ★应用场景
  介绍完并发问题,按照本系列的惯例,最后再来介绍一下双缓冲区在某些场合的应用。
  ◇用于并发线程
  在线程方式下,首先要考虑的是缓冲区的类型:到底用队列方式还是环形方式。这方面的选择依据在介绍环形缓冲区的时候已经阐述过了,此处不再啰嗦(省去不少口水)。
  另一个需要注意的是,某些编程语言或者程序库提供了的线程安全的缓冲区(比如JDK 1.5引入的ArrayBlockingQueue)。由于这种缓冲区会自动为每次的读写进行同步/互斥,所以就把双缓冲的优势抵消掉了。因此,大伙儿在进行缓冲区选型的时候要避开这类缓冲区。
  ◇用于并发进程
在进程间使用双缓冲,先得考察不同IPC类型的特点。由于今天讨论双缓冲的目的是降低同步/互斥的开销,对于那些已经封装了同步/互斥的IPC类型,就没太大必要再去搞双缓冲了(单凭这条就已经排除了好多种IPC类型)。剩下的IPC类型中,比较适合用双缓冲的主要是:共享内存和文件。非常凑巧,这两个玩意儿的特点和适用范围在环形缓冲区的帖子里面也已经介绍过了,又可以节省不少口水 :)
架构设计:生产者/消费者模式:双缓冲区 - 包蒙吉 - IT人社区 - powered by italent.cc 架构设计:生产者/消费者模式:双缓冲区 架构设计:生产者/消费者模式[2]:队列缓冲区 架构设计:生产者/消费者模式 IMS业务架构研究 - 通信知识 - 泰尔通信社区 - Powered by Discuz... 基于模型、模式的技术架构设计 电脑图像设计基础:RGB和CMYK色彩模式 - 我要摄影网 - Powered by Su... 软件的架构与设计模式之什么是架构 PCShow IT社区 - 病毒与网络安全 - 关于svchost.exe(页 1) - powered by Discuz! Archiver 理解jsp模式2架构:MVC设计模式探险 设计模式与软件架构设计|IT168 技术开发 Java线程:并发协作-生产者消费者模型 软件的架构与设计模式之什么是架构-开发者网络-架构-天极Yesky HP DL320 G4服务器如何配置SATA阵列? - 存储时代 - 探客网社区 IT应用经验分享平台 - Powered by Discuz! ITIL中IT基础架构管理模型设计与实现 解决基于tomcat的web应用乱码问题 - J2EE开发者 - web思想社区 关注互联网平台级架构设计,UNIX/LINUX系统管理,项目管理,个人职业规划及RIA,CSS/JS/XML,ASP,PHP,.NET,JSP,数据库性能提升 - Powered by Discuz! 嵌入式系统架构的发展趋势及比较分析|计算机技术交流°═—☆ - 迎客堂 迎客堂论坛!青年休闲社区! - powered by phpwind.net 年轻人,这就是C语言家族的故事 - 程序小王的日志 - IT哇咔技术论坛_中国领先的IT社区 - Powered by Discuz! Tomcat 系统架构与设计模式,第 2 部分: 设计模式分析 奇虎360大事记 - 大话IT - 若人论坛 - Powered by Discuz! 软件的架构与设计模式之什么是架构_QQread.com_巧巧电脑 郎咸平:沃尔玛天天低价背后 剥削消费者压榨生产者 搞笑一句话 | 茶楼乐园 - IT姐妹技术论坛 - Powered by PHPWind 印刷知识 - 会声会影 - 工具软件使用 - 黑龙江IT资讯网 - Powered by ...