【Linux】线程安全-生产者消费者模型
文章目录
- 生产者消费者模型
- 123规则
- 应用场景
- 优点
- 忙闲不均
- 生产者和消费者解耦
- 支持高并发
- 代码模拟
生产者消费者模型
123规则
1个线程安全的队列:只要保证先进先出特性的数据结构都可以称为队列
这个队列要保证互斥(就是保证当前只有一个线程对队列进行操作,其他线程不可以同时来操作),还要保证同步,当生产者将队列中填充满了之后要通知消费者来进行消费,消费者消费之后通知生产者来进行生产。
队列起到了生产者和消费者的缓冲作用,生产者不用因为没有人消费发愁,只需要将生产的数据放到队列中即可;消费者不用因为生产者生产了大量数据而发愁,只需要正常关注正在处理的数据即可
2个角色的线程:生产者和消费者
3个规则:生产者和生产者互斥、消费者和消费者互斥、生产者和消费者互斥+同步
应用场景
比如说微信的后台程序:在不同的场景下一个进程可以是消费者也可以是生产者

优点
忙闲不均
在同一时刻可能接收消息的线程不忙而处理消息的线程一直处于工作状态
生产者和消费者解耦
生产者只关心生产,关心队列是否有空闲空间;
消费者只关心消费,关心队列中是否有数据可用。
生产者和消费者不是串行的执行(串行的处理就是当一个线程接收到消息后才可以处理消息,并且只有处理完了之后才可以发送消息,是一个串行的过程),而生产者消费者模型将生产者和消费者解耦,接收消息的一辈子就接收消息,处理消息的一辈子就处理消息,发送消息一辈子就只发送消息,不受其他线程的影响
支持高并发
同一时刻多个人发送消息这种情况是支持的,因为接收消息的线程只需要接收消息,不用干其他事情,所以接收线程接收消息的速度很快
代码模拟
采用互斥和同步实现:
#include<stdio.h>
#include<iostream>
#include<queue>
#include<unistd.h>
#include<pthread.h>
using namespace std;
#define THREAD_COUNT 1//生产者和消费者数量
//创建线程安全队列
class RingQueue{
public:RingQueue(){capacity = 1;pthread_mutex_init(&que_lock, NULL);pthread_cond_init(&consum_cond, NULL);pthread_cond_init(&product_cond, NULL);}~RingQueue(){pthread_mutex_destroy(&que_lock);pthread_cond_destroy(&consum_cond);pthread_cond_destroy(&product_cond);}//往队列中放数据,生产void Push(int data){pthread_mutex_lock(&que_lock);while(que.size()>=capacity){pthread_cond_wait(&product_cond, &que_lock);//为什么要用while循环呢?//因为当生产者被唤醒后,需要再次判断队列是否可以满足生产的条件//生产者或者消费者都是需要在等待结束后再次判断的}que.push(data);//生产,往队列中放入数据cout<<"I am product: " << pthread_self() << "I product number is " << data << endl;pthread_mutex_unlock(&que_lock);pthread_cond_signal(&consum_cond);//生产者完成生产后唤醒消费者线程让消费者进行消费}//从队列中取数据,消费int Pop(){pthread_mutex_lock(&que_lock);while(que.size() <= 0){pthread_cond_wait(&consum_cond, &que_lock);}int data = que.front();que.pop();cout<<"I am consume: " << pthread_self() << "I consume number is " << data << endl;pthread_mutex_unlock(&que_lock);pthread_cond_signal(&product_cond);//消费者线程消费之后通知生产者来生产return data;}private:queue<int> que;//线程安全的队列//给队列一把锁,保证互斥,保证同一时刻只有一个线程对队列进行操作pthread_mutex_t que_lock;//同步的条件变量,队列有元素,消息,没有元素等待,唤醒生产者//保证生产者在队列中没有元素的时候进行生产(插入元素)pthread_cond_t consum_cond;pthread_cond_t product_cond;int capacity;//队列容量,队列元素大于容量表示队满,不再往里插入元素
};
int g_val = 0;
pthread_mutex_t g_val_lock = PTHREAD_MUTEX_INITIALIZER;//静态初始化保护g_val的互斥锁
void* product_thread_start(void* arg){RingQueue *q = (RingQueue*)arg;while(1){pthread_mutex_lock(&g_val_lock);//获取g_val的互斥锁q->Push(g_val);g_val++;sleep(1);pthread_mutex_unlock(&g_val_lock);}
}
void* consum_thread_start(void* arg){RingQueue *q = (RingQueue*)arg;while(1){q->Pop();}
}
int main(){pthread_t consum_tid[THREAD_COUNT];pthread_t product_tid[THREAD_COUNT];RingQueue* q = new RingQueue();for(int i=0; i<THREAD_COUNT; ++i){int ret = pthread_create(&consum_tid[i], NULL, consum_thread_start, (void*)q);if(ret < 0){perror("pthread_create");return 0;}ret = pthread_create(&product_tid[i], NULL, product_thread_start, (void*)q);if(ret < 0){perror("pthread_create");return 0;}}for(int i=0; i<THREAD_COUNT; ++i){pthread_join(consum_tid[i], NULL);pthread_join(product_tid[i], NULL);}delete q;return 0;
}
执行结果:

可以看到有效的控制了生产者和消费者的消费顺序,当生产者生产一个消费者就消费一个,消费者消费后生产者接着生产
相关文章:
【Linux】线程安全-生产者消费者模型
文章目录 生产者消费者模型123规则应用场景优点忙闲不均生产者和消费者解耦支持高并发 代码模拟 生产者消费者模型 123规则 1个线程安全的队列:只要保证先进先出特性的数据结构都可以称为队列 这个队列要保证互斥(就是保证当前只有一个线程对队列进行操…...
优化(2) 2023/09/03
今天重新温习了下clean abap,以前只是偶尔打开看几眼。今天把有些自己不熟悉的地方,重点研究了下。有几个点可以在以后工作使用。这几点可能并不能提升程序效率,但会大大提高代码可读性和代码的可扩展性: 用insert XXX into tabl…...
Swap and Reverse 题解
Swap and Reverse 题面翻译 题目描述 本题共有 t t t 组数据。 给定一个长度为 n n n 的字符串 s s s 和一个整数 k k k, s s s 只包含小写字母,你可以进行若干次操作(可以是零次),具体操作如下: 选…...
单元测试:优雅编写Kotlin单元测试
一、MockK简介 MockK是一款功能强大、易于使用的Kotlin mocking框架。在编写单元测试时,MockK能够帮助我们简化代码、提高测试覆盖率,并改善测试的可维护性。除了基本用法外,MockK还提供了许多额外的功能和灵活的用法,让我们能够…...
深度学习入门教学——卷积神经网络CNN
目录 一、CNN简介 一、输入层 二、卷积层 三、池化层 四、全连接层 一、CNN简介 1、应用领域 检测任务 分类与检索 超分辨率重构 2、卷积网络与传统网咯的区别 传统神经网络和卷积神经网络都是用来提取特征的。神经网络: 可以将其看作是一个二维的。卷积神经…...
【MySQL】MySQL系统变量(system variables)列表(mysqld --verbose --help的结果例)
文章目录 【MySQL】MySQL系统变量(system variables)列表(mysqld --verbose --help的结果例)mysqld --verbose --help的结果例参考 【免责声明】文章仅供学习交流,观点代表个人,与任何公司无关。 编辑|SQL和…...
Python学习之四 数据输入与输出
(一) 脚本编程 前面的章节,组要学习了一些简单的Python编程,使用的是交互式解释器,本章节将开始进行脚本编程。可以使用多种编辑器或者IDE完成编码,主要使用vim。 参考前续小节的写法,我们给a、b分别赋值3和5。 在终端运行程序后发现,没有任何输出。这就是本次我们将要…...
VBA技术资料MF51:VBA_在Excel中突出显示唯一值
【分享成果,随喜正能量】世间万物,因果循环不休,你的善心善行,都可能成为你的善缘善果。每天忆佛念佛,每天都在佛菩萨的加持下生活,自然吉祥如意,法喜充满。 。 我给VBA的定义:VBA是…...
Mqtt学习笔记--交叉编译移植(1)
简述 Mqtt目前在物联网行业的应用比较多,mqtt属于应用层的一个中间件,这个中间件实现消息的订阅发布机制。网上介绍Mqtt的实现原来的比较多,这里不细介绍。 其实在我们之前的产品中,自己也开发的有类似的中间件,除了具…...
Gateway的服务网关
Gateway服务网关 Gateway网关是我们服务的守门神,所有微服务的统一入口。 网关的核心功能特性: 请求路由 权限控制 限流 架构如下: gateway使用 引入依赖 创建gateway服务,引入依赖 <!--网关--> <dependency>…...
信息化发展18
存储技术 1 、存储分类 2 、常用存储模式的技术与应用对比: ( 1 ) 存储虚拟化( Storage Virtualization ) 是“ 云存储” 的核心技术之一。 它带给人们直接的好处是提高了存储利用率, 降低了存储成本, 简…...
TypeScript学习 + 贪吃蛇项目
TypeSCript简介 TypeScript是JavaScript的超集。它对JS进行了扩展,向JS中引入了类型的概念,并添加了许多新的特性。TS代码需要通过编译器编译为JS,然后再交由JS解析器执行。TS完全兼容JS,换言之,任何的JS代码都可以直…...
YOLO-NAS详细教程-介绍如何进行物体检测
对象检测是计算机视觉中的一项核心任务,可以检测和分类图像中的边界框。自从深度学习首次取得突破以来,它就以极快的速度获得普及和普及,并推动了医疗领域、监控、智能购物等众多公司的发展。考虑到它最终满足了两个基本需求,这一点也就不足为奇了端到端方式:找到所有当前…...
容器没有命令时,如何查看进程、容器executable file not found in $PATH: unknown
前言 当容器没有ps -ef命令时,可以通过以下的命令来查看容器的进程。 docker container top查看容器运行的进程(该命令很有用) #docker container top 命令用于查看容器运行的进程 #当容器里面没有ps -ef命令时,使用docker con…...
如何使用 Amazon EMR 在 Amazon EKS 上构建可靠、高效、用户友好的 Spark 平台
这是 SafeGraph 技术主管经理 Nan Zhu 与亚马逊云科技高级解决方案架构师 Dave Thibault 共同撰写的特约文章。 SafeGraph 是一家地理空间数据公司,管理着全球超过 4100 万个兴趣点(POI,Point of Interest),提供品牌隶…...
国产IDE如何获得捐赠和风险投资
有人在开发VB6 脚本工具,有人在开发VB6的插件,把VB6变成VSCODE界面模式,再加上NUGET,NPM等包管理器原理的在线组件、源码下载功能。 还有TWINBASIC几乎80%代替了VB6,radbasic一直封闭,听说也收到了不少众筹…...
【数学建模】清风数模正课5 相关性分析
相关系数 相关性分析的关键是计算相关系数,在本节课中将会介绍两种常用的相关系数:皮尔逊相关系数(Pearson)和斯皮尔曼相关系数(Spearman)。 它们可以用来衡量两个变量间相关性的大小,对于不同…...
Java设计模式:一、六大设计原则-03:里氏替换原则
文章目录 一、定义:里氏替换原则1.1 里氏替换原则1.2 里氏替换原则的作用 二、模拟场景:里氏替换原则三、违背方案:里氏替换原则3.1 工程结构3.2 储蓄卡和信用卡3.2.1 储蓄卡3.2.2 信用卡 3.3 单元测试3.3.1 储蓄卡测试3.3.2 信用卡测试 四、…...
jmeter 固定定时器
固定定时器(Constant Timer)是一个定时器元件,可以在线程组中的每个线程之间添加固定的延迟时间。固定定时器会对每个线程的执行进行一定的暂停。 聊一下和线程组中的调度器对线程组执行时长的影响: 相同: 都会影响线…...
【微服务部署】07-调用链追踪
文章目录 集成SkyWalking实现调用链追踪1. SkyWalking架构图2. 代码集成SkyWalking 集成SkyWalking实现调用链追踪 1. SkyWalking架构图 Receiver是SkyWalking的入口,支持gRPC和HTTP协议。 SkyWalking内部有分析和查询两个部分 存储方面SkyWalking支持Elasticsearc…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...
PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...
