并发无锁队列学习之二【单生产者单消费者】

1、前言

  

  最近工作比较忙,加班较多,每天晚上回到家10点多了。我不知道自己还能坚持多久,既然选择了就要做到最好。写博客的少了。总觉得少了点什么,需要继续学习。今天继续上个开篇写,介绍单生产者单消费者模型的队列。根据写入队列的内容是定长还是变长,分为单生产者单消费者定长队列和单生产者单消费者变长队列两种。单生产者单消费者模型的队列操作过程是不需要进行加锁的。生产者通过写索引控制入队操作,消费者通过读索引控制出队列操作。二者相互之间对索引是独享,不存在竞争关系。如下图所示:

2、单生产者单消费者定长队列

  这种队列要求每次入队和出队的内容是定长的,即生产者写入队列和消费者读取队列的内容大小事相同的。linux内核中的kfifo就是这种队列,提供了读和写两个索引。单生产者单消费者队列数据结构定义如下所示:

typedef struct
{
    uint32_t r_index; /*读指针*/
    uint32_t w_index; /*写指针*/
    uint32_t size;    /*缓冲区大小*/
    char *buff[0];    /*缓冲区起始地址*/
}ring_buff_st;

为了方便计算位置,设置队列的大小为2的次幂。这样可以将之前的取余操作转换为位操作,即r_index = r_index % size 与 r_index = r_index & (size -1)等价。位操作非常快,充分利用了二进制的特征。
(1)队列初始状态,读写索引相等,此时队列为空。

  

(2)写入队列

写操作即进行入队操作,入队有三种场景,

2.1 写索引大于等于读索引

2.2写索引小于读索引

2.3.写索引后不够写入一个

(3)读取队列

读队列分为三种场景

3.1写索引大于等于读索引

3.2写索引小于读索引

3.3.读索引后面不够一个

3、单生产者单消费者变长队列

  有些时候生产者每次写入的数据长度是不确定的,导致写入队列的数据时变长的。这样为了充分利用队列,需要增加一个结束索引,保证队列末尾至少能够写入一个数据。变长队列数据结构定义如下:

typedef struct
{
    uint32_t r_index; /*读指针*/
    uint32_t w_index; /*写指针*/
    uint32_t e_index; /*队列结束指针*/
    uint32_t size;    /*缓冲区大小*/
    char *buff[0];    /*缓冲区起始地址*/
}ring_buff_st;

转载于:https://www.cnblogs.com/Anker/p/3864230.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值