锁的底层必然有着原子操作,而其设计为通用场景使用,我们抛弃锁的使用,直接从更细粒度来使用原子操作确保队列的一致性————称为无锁队列
什么样的队列可以支持并发的多生产者多消费者?
- 确保并发的copy过程互不影响;
- 确保并发的指针更新操作原子不丢失。(指针操作无非是值的操作,不存在顺序问题)
如何确保上述两点?
最粗暴的方式就是直接加一把大锁,确保每个producer/consumer的copy + 指针更新这个完整过程是原子的。
显然这个锁太大了,不好。
确保上述两点的另一种方式
- copy前原子更新指针,提前占据需要的空间。通过提前占据确保copy的互不影响。
- copy后原子不丢失的更新指针,这又分成两派:
+ 并发的porducer/consumer 自己原子更新自己copy的值;
+ 交给某个producer/consumer一把更新这次并发过程中的所有copy量。
实现了上述两点,我们也就实现了一个无锁队列。上述方式中,一般无锁队列中的空间处于4种状态:- 明确有数据的:消费于此
- 明确有空间的:生产于此
- data-pending: 正在生产数据中,没有完成copy后指针更新
- space-pending: 正在消费数据中,没有完成copy后指针更新
参考
linux无锁队列的实现 https://lwn.net/Articles/340400/
freebsd无锁队列的实现
dpdk无锁队列的实现https://dpdk-docs.readthedocs.io/en/latest/prog_guide/ring_lib.html
无锁队列的实现,linux阅码场https://cloud.tencent.com/developer/article/1706184
其他
锁确保原子性,屏障确保顺序性。
基于链的无锁队列的关键就是:使用CAS解决挂链操作与指针更新操作之间无法原子性。链式队列中天生没有copy的干扰问题。但是存在着ABA问题。详见参考。