一、简介

1、循环缓冲区的实现原理

环形缓冲区通常有一个读指针和一个写指针。读指针指向环形缓冲区中可读的数据,写指针指向环形缓冲区中可写的缓冲区。通过移动读指针和写指针就可以实现缓冲区的数据读取和写入。在通常情况下,环形缓冲区的读用户仅仅会影响读指针,而写用户仅仅会影响写指针。如果仅仅有一个读用户和一个写用户,那么不需要添加互斥保护机制就可以保证数据的正确性。如果有多个读写用户访问环形缓冲区,那么必须添加互斥保护机制来确保多个用户互斥访问环形缓冲区。

2、概念

关于循环缓冲区(Ring Buffer)的概念,其实来自于Linux内核(Maybe),是为解决某些特殊情况下的竞争问题提供了一种免锁的方法。这种特殊的情况就是当生产者和消费者都只有一个,而在其它情况下使用它也是必须要加锁的。对应在Linux内核中有对它的定义:

struct kfifo {

unsigned char *buffer;

unsigned int size;

unsigned int in;

unsigned int out;

spinlock_t *lock;

};

其中buffer指向存放数据的缓冲区,size是缓冲区的大小,in是写指针下标,out是读指针下标,lock是加到struct kfifo上的自旋锁(上面说不加锁不是这里的锁),防止多个进程并发访问此数据结构。当in==out时,说明缓冲区为空;当(in-out)==size时,说明缓冲区已满。

注:我们保有对应的读写指针,当第一批数据(蓝色)完成,第二批数据(红色)会根据当前的写指针位置继续我们的数据操作,当达到最大的Buffer_Size时,会重新回到Buffer的开始端。

我们更多要说的是Ring Buffer关于在我们在日志处理方面的一个应用,我们知道对于Program来说日志记录提供了故障前应用程序状态的详细信息,在一段时间的运行过程中,会将不断地产生大量的跟踪数据,以及调试信息并持续地将其写入到磁盘上的文本文件中。多亿进行有效的日志记录,需要使用大量的磁盘空间,并且在多线程环境中,所需的磁盘空间会成倍地增加。常规的日志处理来说存在一些问题,比如硬盘空间的可用性,以及在对一个文件写入数据时磁盘 I/O 的速度较慢。持续地对磁盘进行写入操作可能会极大地降低程序的性能,导致其运行速度缓慢。通常,可以通过使用日志轮换策略来解决空间问题,将日志保存在几个文件中,当这些文件大小达到某个预定义的字节数时,对它们进行截断和覆盖。

所以要克服空间问题并实现磁盘 I/O 的最小化,某些程序可以将它们的跟踪数据记录在内存中,仅当请求时才转储这些数据。这个循环的、内存中的缓冲区称为循环缓冲区。它可以将相关的数据保存在内存中,而不是每次都将其写入到磁盘上的文件中。在需要的时候(比如当用户请求将内存数据转储到文件中时、程序检测到一个错误时,或者由于非法的操作或者接收到的信号而引起程序崩溃时)可以将内存中的数据转储到磁盘。循环缓冲区日志记录由一个固定大小的内存缓冲区构成,进程使用这个内存缓冲区进行日志记录。

当然现在我们面对的大多是多线程的协同工作,对于日志记录来说,倘若采取传统的加锁机制访问我们的存储文件,这些线程将在获得和释放锁上花费了大部分的时间,所以采取循环缓冲区会是一个不错的办法。通过使得每个线程将数据写入到它自己的内存块,就可以完全避免同步问题。当收到来自用户的转储数据的请求时,每个线程获得一个锁,并将其转储到中心位置。或者分配一个很大的全局内存块,并将其划分为较小的槽位,其中每个槽位都可由一个线程用来进行日志记录。每个线程只能够读写它自己的槽位,而不是整个缓冲区。当每个线程第一次尝试写入数据时,它会尝试寻找一个空的内存槽位,并将其标记为忙碌。当线程获得了一个特定的槽位时,可以将跟踪槽位使用情况的位图中相应的位设置为1,当该线程退出时,重新将这个位设置为 0。在这里需要同时需要维护当前使用的槽位编号的全局列表,以及正在使用它的线程的线程信息。

但是这里需要注意的是当一个线程已经死亡,却没有释放相应的槽位,并在垃圾收集器释放该槽位之前,再次使用了这个线程 ID 并为其分配一个新的槽位。对于新的线程来说,检查全局列表并且重用相同的槽位(如果以前的实例使用了它的话),这是非常重要的。因为垃圾收集器线程和写入者线程可能同时尝试修改全局列表,所以同样也需要使用某种锁定机制。

二、Ring Buffer的优点

我们使用 Ring Buffer 这种数据结构,是因为它给我们提供了可靠的消息传递特性。这个理由就足够了,不过它还有一些其他的优点。

首先,Ring Buffer 比链表要快,因为它是数组,而且有一个容易预测的访问模式。这很不错,对 CPU 高速缓存友好 (CPU-cache-friendly)-数据可以在硬件层面预加载到高速缓存,因此 CPU 不需要经常回到主内存 RAM 里去寻找 Ring Buffer 的下一条数据。

第二点,Ring Buffer 是一个数组,你可以预先分配内存,并保持数组元素永远有效。这意味着内存垃圾收集(GC)在这种情况下几乎什么也不用做。此外,也不像链表那样每增加一条数据都要创建对象-当这些数据从链表里删除时,这些对象都要被清理掉。

参考网址:

图片说明:

ringbuffer java_循环缓冲区(RingBuffer)相关推荐

  1. 环形缓冲区ringbuffer c++类模版实现

    @ringbuffer 环形缓冲区ringbuffer c++类模版实现 使用方法: 1.将ringBuffer.h文件拷贝到开发工程中,添加相应的头文件 2.需要g++编译器(开发的项目工程需要支持 ...

  2. 【C++】31. Boost::circular_buffer——循环缓冲区

    一.概述 Boost.Circular_buffer维护了一块连续内存块作为缓存区,当缓存区内的数据存满时,继续存入数据就覆盖掉旧的数据. 它是一个与STL兼容的容器,类似于 std::list或st ...

  3. Boost:循环缓冲区总和的测试程序

    Boost:循环缓冲区总和的测试程序 实现功能 C++实现代码 实现功能 循环缓冲区总和的测试程序 C++实现代码 #include <boost/circular_buffer.hpp> ...

  4. Boost:循环缓冲区迭代的测试程序

    Boost:循环缓冲区迭代的测试程序 实现功能 C++实现代码 实现功能 循环缓冲区迭代的测试程序 C++实现代码 #undef BOOST_CB_ENABLE_DEBUG #define BOOST ...

  5. linux内核中的循环缓冲区

    Linux内核中的循环缓冲区(circular buffer)为解决某些特殊情况下的竞争问题提供了一种免锁的方法.这种特殊的情况就是当生产者和消费者都只有一个,而在其它情况下使用它也是必须要加锁的. ...

  6. C#中的通用循环缓冲区

    目录 介绍 概念化这个混乱 使用这个混乱 兴趣点 下载Circular-master.zip-14.4 KB 介绍 微软.NET提供了一些基本的通用数据结构,例如Stack<T>.Queu ...

  7. linux 循环缓冲区 源码,Linux中的循环缓冲区

    在学习到 并发和竞态 时,其中的提到了缓冲区,用于实现免锁算法,这里转载的是大神有关循环缓冲区做的一些操作. 其中源代码在最下面的附件中,有关作者的讲解感觉很清晰,很好,不过这里说一下自己的见解: 点 ...

  8. Android 循环缓冲区

    由于需要将接受到的视频编码数据取出每一帧,需要用到循环缓冲区.在网上找了个c++版,改成了java版. public class CirCleBufer { private static boolea ...

  9. linux+循环buffer,说说循环缓冲区(Ring Buffer)

    关于循环缓冲区(Ring Buffer)的概念,其实来自于Linux内核(Maybe),是为解决某些特殊情况下的竞争问题提供了一种免锁的方法.这种特殊的情况就是当生产者和消费者都只有一个,而在其它情况 ...

最新文章

  1. 外媒:社交媒体的大量使用与精神疾病有关
  2. python六十一: __module__属性
  3. mysql 主从热备_windows10本地两个mysql8服务配置主从热备
  4. 【NLP】基于预训练的中文NLP工具介绍:ltp 和 fastHan
  5. Python只需要三十行代码,打造一款简单的人工语音对话
  6. np.c_与np.r_
  7. LeetCode 1124. 表现良好的最长时间段(单调栈/哈希)
  8. some daily
  9. 截至11日14时37分,“11.11京东全球好物节”累计下单金额突破1794亿元
  10. 吴恩达机器学习第五回——支持向量机
  11. spine纹理解包 黑底_本期全欧美阵容!种草了艾玛罗的斑马纹,海狸的针织Bra【海报街拍】...
  12. 梯度下降法与正规方程的比较
  13. Delphi——数组(静态数组和动态数组)、地址和指针
  14. EXCEL 中数据分析常用统计方法介绍(二)
  15. 易优EyouCMS全套插件使用说明
  16. 简单实现网站灰色效果以谨记2020年4月4日悼念日
  17. 隐藏和isa :进化返祖以及白马非马(c++)
  18. Qt实现基于G.729A(G729A)的语音聊天
  19. 准备考试?python也能帮你划重点,上考场
  20. 无人机监控交通流量实时传输路况智慧交通系统说明

热门文章

  1. 接口与抽象类的区别 详细总结
  2. include<cstdio>
  3. LINK : fatal error LNK1104: 无法打开文件“mfc90ud.lib”
  4. js常见案例总结(一)
  5. Delphi函数大全
  6. MATLAB fmincon函数 进阶资料(磕盐记录)
  7. 策略模式的理解与应用
  8. 安全如何为数据库选择最佳加密方法
  9. 计算机输入设备由什么和什么和扫描仪组成,计算机输入设备之扫描仪.ppt
  10. Confluent Platform: ksqlDB 实时数据 ETL