双缓冲的设计和应用

  以前对大文件的读取和处理有过不少疑问,恰好在一个项目中学到并运用了双缓冲的技术,感觉对大文件的操作有了进一步的理解。

  项目的背景大致是为程序中的一些变量绑定数据源文件,程序会自动间隔若干毫秒用数据源中的文件刷新变量。原先的做法是在程序运行之初将所有数据源文件读入内存,并放在各个不同的数组中,间隔某段时间就用数组的内容刷新变量的值,然后读取数组的索引自增。这样的设计主要是考虑到文件读取速度可能赶不上刷新速度,故需先将文件整体放入内存。但这样的设计也带来了很多问题,一是需要绑定数据源的变量数量增多时,内存占用会很可观;二是因为在一开始就讲数据文件读入数组,所以在程序运行过程中不能够替换新的数据文件。针对这些问题,设计了新的双缓冲机制。

  双缓冲多用于图形处理,大概可以简单的理解为刷新图像时尽量大块的刷新,比如在绘图过程中,如果你把所有图形事先画到某种image内存对象上,然后在用这个image一次性刷新屏幕,这应该就是一种缓冲。这里的双缓冲主要的意思也类似。个人认为,缓冲的本质就是:通过某些方法,解决某几个操作在时间或空间上的异步性。而双缓冲就是一种能够使得这种异步性能完全消除的诸多解决方案中,比较简单的一种。就拿这篇文章的背景所述的读取文件的例子,这个例子中的问题同时体现在时间以及空间上:时间上一个操作要求连续不断地读取数据,另一个操作则间断地提供数据(即读入文件);空间上一个操作要求连续的小量的数据,另一个操作则间断地提供大量数据,那么由上述本质可以看出,这些操作间需要有缓冲来解决时空异步的问题。而双缓冲在这个例子中,则是为了在时间上能连续地读入而引入的,双缓冲保证无论在哪一个时间点,总有一个缓冲是可读的(重要前提是缓冲的填充时间小于读取缓冲由满至空的时间)。

  本来想以代码的形式作出例子,但觉得缓冲的概念和具体编程语言无关,所以用流程图给出算法:

  1.   首先是两个填充缓冲区的线程,这两个线程很简单:在一个判断是否终止的循环中,等待填充缓冲区信号量,一旦获得信号量,就填充对应缓冲区,具体操作时,可以设置一个BUF_SIZE作为缓冲区大小,填充BUF_SIZE个,同时在填充完毕时更新缓冲区当前剩余可用数据数量为BUF_SIZE,具体的流程如下:
  2.   然后较为重要的就是读取缓冲区的线程,这个线程负责无间断地读取缓冲区,这就要求这个线程在两个缓冲区之间跳转,当Buffer1告罄时直接读取Buffer2,同时释放SemBuf1信号量,Thread1捕捉后会立即填充Buffer1,然后当Buffer2读取告罄时直接读取Buffer1,同时释放SemBuf2,Thread2捕捉此信号量后会立即填充Buffer2。这里值得注意的有两点,第一是在Read线程启动之前,要将Buffer1与Buffer2都准备好,并且要保证两者的准备次序避免混乱,即准备完成Buffer1后才能开始准备Buffer2,Buffer2准备完成后才能启动Read线程;第二点是前面提过的,就是要保证Read线程将一个Buffer从满读至空的时间要小于填充线程将一个Buffer从空填至满的时间,简言之就是保证读取的速率小于填充的速率,这点从背景问题上看出就可以保证(如果这点不能够保证,那么缓冲根本就没有意义,也没有方法可以完成这个问题)。具体流程如下:

  3. 最后是主线程,主线程主要保证以上三个线程的初始启动顺序,流程如下:

 

  说说学习双缓冲时候的几点体会。

  首先是双缓冲本身带来的好处,在这个项目中,双缓冲可以节约内存的使用,无需在程序开始时就讲所有数据读入内存,再一个就是在程序执行过程中,可以切换数据文件,较原先的方法更为灵活。这是在特定背景下解决特定问题。然而,缓冲是一个普遍的概念,这样的方法也可以运用到其他“操作在时空上异步”的情景下,解决一系列类似的问题,这是在一般的场景下解决一般问题。

  再有一点个人认为比较重要的体会,就是整个学习的过程,从特殊的问题入手,通过有针对性的方法解决,然后从某几个有针对的方法中总结规律得到问题本质,再由这个本质推演得到普适性的方法,从而解决一般的问题。这是一种很好的学习方法,简言之就是举一反三。

  第一篇博文到此结束,欢迎大家指正。

 

 

 

转载于:https://www.cnblogs.com/melonboy/archive/2012/12/10/2800598.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值