环形缓冲区用固定数组和读写索引实现 FIFO。写指针到末尾后回绕到开头,因此无需移动已有数据,适合网络收发、音视频和单生产者单消费者队列。它的难点不在取模,而在于满与空的语义、索引发布顺序和容量满后的业务策略。

写入 tail 位置tail 环绕递增消费者读取 headhead 环绕递增
队列图数据写入完成后再发布 tail,读取完成后再推进 head。
storage固定容量槽位,生命周期不随每条消息频繁分配释放。head消费者下一次读取的位置,只由消费者推进。tail生产者下一次写入的位置,只由生产者推进。满与空可保留一个空槽,或使用单独计数/序号避免歧义。发布顺序先写数据再发布索引,消费者才不会读到半条消息。背压策略满时阻塞、丢新、丢旧或覆盖必须由业务截止期决定。

SPSC 的简单来自所有权明确

单生产者单消费者场景下,生产者只写 tail 和对应槽位,消费者只写 head 和对应槽位,索引可用合适的原子加载和存储协调。关键是生产者在数据完全写入后再发布 tail,消费者在读完数据后再发布 head;否则 CPU 重排序或编译器优化可能让另一端看到不完整内容。

多生产者或多消费者不能只把两个索引改成原子变量。多个线程可能竞争同一槽位,需要额外的序号、CAS 协议或每槽状态,并且要处理线程暂停后留下的空洞。选择 MPMC 算法前先确认是否真的需要它,很多系统通过单一收发线程就能保持简单可靠。

队列满时保什么,决定系统行为

日志和遥测可能允许丢旧数据,控制命令和资源释放消息则通常不能丢。不要把“缓冲区更大”当成唯一答案,它只会推迟拥塞并增加延迟。为每类消息定义容量、最大等待、丢弃计数和告警阈值,队列才是可观测的流量控制点。

参考:环形缓冲区设计与实现