两个生产者之后:给无锁环形队列加同步的三条路
前作讲 kfifo 时留了一句狠话:
前作:一个没有名字的持久化设计
每根指针都满足"单写多读",配合内存屏障保证可见性,锁就是多余的。这个前提一旦被打破(两个生产者),无锁立刻失效,必须自己加同步。
上一篇把翻车现场拍成了慢动作——head++ 是读-改-写三步,两个生产者同读到 head=5,一个元素静默丢失。这篇接着走下一步:怎么修。原文给了三条出路的目录但没给代码,这里补全。
前作讲 kfifo 时留了一句狠话:
前作:一个没有名字的持久化设计
每根指针都满足"单写多读",配合内存屏障保证可见性,锁就是多余的。这个前提一旦被打破(两个生产者),无锁立刻失效,必须自己加同步。
上一篇把翻车现场拍成了慢动作——head++ 是读-改-写三步,两个生产者同读到 head=5,一个元素静默丢失。这篇接着走下一步:怎么修。原文给了三条出路的目录但没给代码,这里补全。
上一篇讲五个经典存储思想时,kfifo 一节带过了一句:单生产者单消费者场景下完全无锁。一句带过其实亏了——这句话背后是一整套可以迁移的并发设计纪律。这篇展开讲:锁到底贵在哪、写者唯一性为什么能消解冲突、"写了不等于看得见"怎么破、以及两个生产者进场后翻车有多快。
最近在 review 一个布谷鸟过滤器分片的持久化方案:槽位环、脏槽位、双代文件、index 位图翻转,一整套组合拳。review 的人问了句"这套设计叫什么名字",我卡住了——它没有名字,因为它是五个经典思想的排列组合。每个零件单独拿出来都有出处,拼在一起就成了"自研"。
这篇文章把这五个思想逐个拆开,讲清楚它们各自从哪来、在哪些经典系统里出现过、为什么长成那个样子。下次你遇到类似设计,可以直接报出人名和论文,而不是"我们内部叫它 V4"。