手撕环形队列系列三:多生产者并行写入
本文是手撕环形队列系列的第三篇,之前的文章链接如下:
之前系列文章介绍的环形队列,已经能够支持多生产者和多消费者并发操作,数据操作模式为:
生产者准备好数据,然后 push()方法放入环形队列中;
消费者准备好接收的缓冲区,然后调用 pop()方法将数据写入接收缓冲区中。
这种模式下,生产者准备数据过程中,需要分配内存。把数据写入环形队列后,这个内存就不需要了,得释放掉。这样,会导致生产者频繁进行内存分配和释放的动作。
因此,对性能要求更苛刻的系统,希望生产者能直接使用环形队列中的内存,直接写入,这样就不需要生产者再分配内存了。这种思路下,环形队列和生产者之间的交互关系变为:
生产者调用 ring_queue.request_push()方法,获得一个可以写入的 token;
生产者通过 token 获取内存地址,向这个地址进行数据写入, 把数据都写好;
生产者调用 token.finish()方法, 通知环形队列已经完成写入。
多个生产者可以并行操作,用图示意如下:
上图中,环形队列中的元素,用三种不同颜色来区分:
可写入区域:可以写入的位置区域;
正在写入区域:已经分配出去,producer 正在进行写入的区域
写入完成区域:producer 写入完成,并且环形队列已经更新其状态的区域。
多个 producer(p1, p2, p3) 并发在环形队列尾部写入,它们的速度不一定相同,因此并发写入区域会形成正在写入区域、写入完成区域互相交错的情况。
这种情况下,消费者读取时,把 tail 作为上限,并且要判断区域是已写入完成状态,才可以读取进行消费。
支持多生产者并行提交的环形队列,C 语言实现代码如下。
本文仅展示了多生产者并行写入,消费者依然是串行消费。(依照本文的思路,小伙伴们可以继续扩展,让多个消费者也能并行消费。)
写个简单的程序,测试一下(不是多线程的,仅为了基本功能演示用):
编译后,运行测试程序,输出如下:
我的微信号是 实力程序员,欢迎大家转发至朋友圈,分享给更多的朋友。
版权声明: 本文为 InfoQ 作者【实力程序员】的原创文章。
原文链接:【http://xie.infoq.cn/article/8db4daed33e5a49e48369d381】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论