news 2026/4/15 10:49:16

实战:用信号量与环形缓冲区实现生产者-消费者模型

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
实战:用信号量与环形缓冲区实现生产者-消费者模型

各类资料学习下载合集
链接:https://pan.quark.cn/s/770d9387db5f

在多线程编程中,生产者-消费者模型是处理数据流的核心模式。上一篇我们讲了“条件变量+互斥锁”的实现方式,今天我们来解锁一种更轻量级的武器——信号量(Semaphore),并结合环形队列来实现高效的数据吞吐。


一、 核心蓝图:双信号量控制

在这个模型中,我们不再关注“互斥锁”来保护整个链表,而是关注资源的数量。我们把固定大小的缓冲区看作两类资源:

  1. 空格子(Blank):供生产者存放数据。
  2. 产品(Product):供消费者提取数据。

1. 信号量定义

我们引入两个信号量:

  • blank_number:表示缓冲区中剩余的空闲位置数量。初始值为NUM(例如 5)。
  • product_number:表示缓冲区中已有的产品数量。初始值为0

2. 环形队列(Ring Buffer)

为了避免频繁的内存分配与释放(如链表节点),我们使用一个固定大小的全局数组queue[NUM]。通过取模运算i = (i + 1) % NUM,让数组下标首尾相接,形成一个环。


二、 生产者实现逻辑

生产者的任务是将数据填入空格子。它的逻辑可以概括为:“申请空格 -> 生产 -> 增加产品”

  1. 等待空格 (sem_wait(&blank_number))
    • blank_number减 1。
    • 如果blank_number为 0(说明缓冲区满了),生产者自动阻塞,等待消费者腾出位置。
  2. 生产产品
    • 将数据写入数组当前位置queue[p]
    • 移动下标p = (p + 1) % NUM
  3. 增加产品 (sem_post(&product_number))
    • product_number加 1。
    • 唤醒可能正在等待产品的消费者。

三、 消费者实现逻辑

消费者的任务是取走产品并腾出空间。它的逻辑概括为:“申请产品 -> 消费 -> 增加空格”

  1. 等待产品 (sem_wait(&product_number))
    • product_number减 1。
    • 如果product_number为 0(说明缓冲区空了),消费者自动阻塞,等待生产者产出。
  2. 消费产品
    • 读取数组当前位置queue[c]的数据。
    • 移动下标c = (c + 1) % NUM
    • (可选)将原位置清零queue[c] = 0,模拟消费动作。
  3. 增加空格 (sem_post(&blank_number))
    • blank_number加 1。
    • 唤醒可能正在等待空格的生产者。

四、 完整代码实现

下面的代码展示了如何使用semaphore.h实现上述逻辑。我们定义缓冲区大小为 5。

#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<pthread.h>#include<semaphore.h>#include
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/12 20:07:37

网络编程入门:B/S 与 C/S 架构深度解析与实战

各类资料学习下载合集 链接:https://pan.quark.cn/s/770d9387db5f 在网络编程的世界里,架构的选择决定了系统的“基因”。是选择打开浏览器就能用的 B/S 架构,还是选择体验极致、功能强大的 C/S 架构?本文将结合理论与代码实战,带你彻底搞懂这两者的区别。 一、 理论核心…

作者头像 李华
网站建设 2026/4/15 9:17:11

Goroutine “气泡”宇宙——Go 并发模型的新维度

大家好&#xff0c;我是Tony Bai。goroutine 是 Go 并发模型的基石&#xff0c;我们习惯于将其视为一个个轻量、独立的执行单元。然而&#xff0c;近年来&#xff0c;Go 语言中出现了一种新的、微妙的并发概念&#xff0c;Go 核心团队的成员们亲切地称之为 “Goroutine 气泡” …

作者头像 李华
网站建设 2026/4/10 2:52:51

Linly-Talker与UCloud大模型平台技术对接

Linly-Talker与UCloud大模型平台技术对接 在虚拟主播、数字员工、AI教师等应用场景日益普及的今天&#xff0c;如何以低成本、高效率构建一个“能听、会说、有表情”的智能数字人系统&#xff0c;成为众多企业和开发者关注的核心问题。传统方案往往依赖复杂的动画制作流程和高昂…

作者头像 李华
网站建设 2026/4/12 22:15:51

Linly-Talker与华为盘古大模型技术对接

Linly-Talker与华为盘古大模型技术对接 在金融客服的晨会上&#xff0c;一位虚拟经理正用标准普通话讲解季度财报&#xff0c;口型精准、语调自然&#xff1b;政务大厅的自助终端前&#xff0c;居民对着屏幕提问社保政策&#xff0c;数字人秒级响应并生成带面部表情的解答视频—…

作者头像 李华
网站建设 2026/4/10 2:16:40

6、深入理解TCP/IP与IPv6:原理、特性及迁移策略

深入理解TCP/IP与IPv6:原理、特性及迁移策略 1. TCP/IP子网计算示例 以B类地址172.16.0.0和子网掩码255.255.254.0为例。该子网掩码的前缀长度为23位,B类地址的默认前缀长度是16位,二者相减得到7。2的7次方为128,这就是使用该子网掩码对B类地址进行子网划分后得到的子网数…

作者头像 李华
网站建设 2026/4/13 12:33:51

16、动态主机配置协议(DHCP)的监控与故障排除

动态主机配置协议(DHCP)的监控与故障排除 1. 监控DHCP租约 可以使用与特定作用域关联的“地址租约”视图来监控已分配的DHCP租约。打开作用域并点击作用域名称下的“地址租约”项,会看到一个易于阅读的列表,其中包含当前该作用域内所有生效租约的信息,具体如下: - 客户…

作者头像 李华