【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…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...
免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
