并发无锁队列学习之二【单生产者单消费者】
2023-09-14 08:59:45 时间
最近工作比较忙,加班较多,每天晚上回到家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;
多线程必考的「生产者 - 消费者」模型,看齐姐这篇文章就够了 生产者 - 消费者模型 Producer-consumer problem 是一个非常经典的多线程并发协作的模型,在分布式系统里非常常见。也是面试中无论中美大厂都非常爱考的一个问题,对应届生问的要少一些,但是对于有工作经验的工程师来说,非常爱考。 这个问题有非常多的版本和解决方式,在本文我重点是和大家壹齐理清思路,由浅入深的思考问题,保证大家看完了都能有所收获。
相关文章
- 并发工具类(三)控制并发线程数的Semaphore
- 《C++ 并发编程》- 第1章 你好,C++的并发世界
- 测试并发应用 (一)监控Lock接口
- PHP 之 curl_multi实现并发
- 并发无锁队列学习之二【单生产者单消费者】
- PHP写的异步高并发服务器,基于libevent
- [转] asp.net解决高并发的方案
- 高并发 Nginx+Lua OpenResty系列(7)——Lua开发库json
- Kotlin 朱涛-16 协程 生命周期 Job 结构化并发
- 【高并发简单解决方案】redis缓存队列+mysql 批量入库+php离线整合
- Java中的同步集合与并发集合有什么区别?
- csv 文件驱动的 jMeter 并发测试
- java并发编程实战读书笔记4--生产者消费者模式和队列
- Java并发编程:如何创建线程?
- Java开发之高并发必备篇(一)——线程基础
- Java软件开发 | 高并发编程篇之——安全访问的集合(2)
- Nginx突破高并发的性能优化 - 运维笔记
- 【并发编程】JUC并发编程(彻底搞懂JUC)
- 消息队列,高并发的救火员