05|环形缓冲区(Ring Buffer)

1. 什么是环形缓冲区

环形缓冲区(Ring Buffer)用一块固定容量的连续内存循环保存数据。写到数组末尾后,从数组开头继续写;读操作同理。它并非物理上的圆环,而是通过下标回绕实现循环使用。

flowchart LR
    A["位置 0"] --> B["位置 1"] --> C["位置 2"] --> D["位置 3"]
    D -- "回绕" --> A
  • 写位置(write):下一次写入的位置。
  • 读位置(read):下一次读取的位置。
  • FIFO:先写入的数据先被读取。
  • 读写后位置向前移动,到末尾则回到起点。

2. 读写位置与空满判断

写入数据时推进写位置;读出数据时推进读位置。不能只看两个位置是否相等来同时判断空和满,必须约定区分方式。

常见方法有两种:

方法空的条件满的条件实际可用容量
预留一个空槽read == write写位置再前进一步就碰到读位置N - 1
额外记录有效长度有效长度为 0有效长度为 NN

以容量 8、预留一个空槽为例:

flowchart LR
    subgraph Buffer["8 个物理槽位"]
      direction LR
      A["0 已占"] --- B["1 已占"] --- C["2 已占"] --- D["3 已占"] --- E["4 已占"] --- F["5 已占"] --- G["6 已占"] --- H["7 空槽"]
    end

此时若 read = 0、write = 7,继续写入会让写位置回到 0,与读位置重合,因此判定为满;8 个槽位中最多存 7 个数据。

3. 优缺点与适用场景

优点

  • 空间固定、可反复利用,通常无需动态分配。
  • 入队和出队只需移动位置,单个元素的基本操作通常是 O(1)。
  • 适合持续产生、持续消费的数据流。

局限

  • 容量有上限;写入速度长期快于读取速度时,会遇到缓冲区满。
  • 满时必须明确策略:拒绝新数据、覆盖旧数据或等待可用空间。
  • 多线程或中断并发访问时,需要额外考虑同步与数据可见性。

常见应用:串口收发、音频采样流、日志暂存、生产者—消费者之间的数据传递。

4. 核心结论

环形缓冲区的本质是:固定数组 + 可回绕的读写位置 + 明确的空满规则。选择它时,重点考虑数据流是否连续、容量如何估算,以及缓冲区满时允许怎样处理数据。