lock-free ring buffer¶
是什么 / 解决什么问题¶
ring buffer 用固定大小数组在生产者和消费者之间传递消息。低延迟系统喜欢它,因为不需要频繁分配内存,数据布局连续,延迟更稳定。
SPSC 模型¶
单生产者单消费者是最简单也最常用的形式:
生产者只写 head,消费者只写 tail。双方读取对方的 index 来判断满/空。
核心语义¶
- 写数据必须发生在发布
head之前。 - 读数据必须发生在观察到
head之后。 head和tail应避免 false sharing。- 容量通常取 2 的幂,用 mask 替代取模。
C++ 原子顺序¶
// producer
buffer[pos] = item;
head.store(next, std::memory_order_release);
// consumer
auto h = head.load(std::memory_order_acquire);
item = buffer[pos];
release/acquire 建立可见性关系:消费者看到新的 head 后,也能看到生产者之前写入的 slot 数据。
背压¶
队列满时必须有策略:
- 返回失败,让上游限速
- 覆盖旧数据,适合某些行情快照场景
- 自旋等待,适合独占核心
- 降级丢弃,必须记录指标
面试高频问题¶
lock-free 是否一定更快¶
不一定。低竞争下 mutex 可能足够快;复杂 lock-free 结构可能增加 cache miss、ABA 和调试成本。交易系统常用简单、固定模型的 SPSC 队列,而不是追求通用 lock-free 容器。
MPSC/MPMC 为什么更难¶
多个生产者或消费者会竞争同一个 index,需要 CAS 或分段设计;还要处理发布顺序、空洞、ABA、内存回收等问题。