高效无锁环形队列

Posted HeroKern

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高效无锁环形队列相关的知识,希望对你有一定的参考价值。

在linux零拷贝技术中提到高效无锁环形队列,这篇文章分享这个知识点,这个知识点不是很复杂。环形队列多用于多线程之间数据异步传输,提高数据处理性能。下面介绍常规环形队列和高效无锁队列两种处理方式。
常规环形队列如下图所示,队列头代表写指针,队列尾代表读指针,通过判断读写的位置判断队列是否为空,是否满,通过线程锁来保证读写指针在使用时只被一个线程使用,从而保证数据不会出错。(出错原因,当一个线程在对读写指针修改时,调度器将该线程切换出去访问另外一个线程,如果该线程正好也会对读写指针进行修改,那么就会导致读写指针被污染而不能继续使用)。

环形队列初始化代码如下:

读写指针相等代表队列为空,写指针加一等于读指针代表队列未满,这里需要注意队列缓存从尾部跳转到头部这个临界值需要单独处理。
读队列处理函数如下图所示。读取队列首先应该判断该队列是否为空,如果没有数据就休眠等待有数据,有数据就取出数据并且让读指针加一,加满到队列大小后就重新从0位置开始。
注意:pthread_cond_wait这里不存在死锁情况,该函数内部为自动调用pthread_mutex_unlock函数进行解锁。当等到pthread_cond_signal该信号时候就退出休眠自动调用pthread_mutex_lock函数上锁。

环形队列写函数如下所示。需要对队列操作时需要上锁,然后判断队列是否未满,如果队列满了就退出,未满就可以向队列中写数据,同时写指针加一,同时出发条件变量信号。注意:pthread_cond_signal和pthread_cond_wait函数不需要一一对应,及时没有进入pthread_cond_wait等待状态,也不影响pthread_cond_signal函数,pthread_cond_signa不存在累计的情况。
以上就是常规环形队列处理方式,pthread_mutex_lock函数是阻塞方式获取锁,比较耗时效率相对低。

高效无锁队列
高效无锁队列与环形队列思想基本一致,只是去掉了互斥锁部分,引入了标志位。高效无锁队列如下所示。

队列分布于常规队列一致,在队列每项前面添加了一个标志位,就是图中红色部分,标志位 用于判断该像目前的状态,一共有可以写(CAN_WRITE),可以读(CAN_READ),正在读(READING),正在写(WRITING)四种状态。
初始化如下所示。代码思想比较简单就不在讲解代码了。

取数据函数如下所示。

写数据函数如下所示。写数据之前需要判断是否有可以写的地址,以阻塞方式去取写地址。

给队列写数据就需要去获取可用的队列地址,阻塞方式获取到可以使用的队列地址,同时让下指针加一,读队列会去判断队列是否有数据。该方式判断是通过标志位进行判断的,这种方式在实际使用场景比较多,特别裸奔程序中(就是不上系统,像单片机程序)。

总结
本文分享了常规环形队列和高效无锁队列,这两种方式在实际应用中比较多,有需要技术支持的联系:yolov8。

以上是关于高效无锁环形队列的主要内容,如果未能解决你的问题,请参考以下文章

高效无锁环形队列

高效无锁环形队列

使用无锁队列(环形缓冲区)注意事项

dpdk无锁队列rte_ring实现分析

dpdk无锁队列rte_ring实现分析

环形队列-高效定时触发