线程同步--生产者消费者模型

文章目录
- 一.条件变量
- pthread线程库提供的条件变量操作
- 二.生产者消费者模型
- 生产者消费者模型的高效性
- 基于环形队列实现生产者消费者模型中的数据容器
一.条件变量
- 条件变量是线程间共享的全局变量,线程间可以通过条件变量进行同步控制
- 条件变量的使用必须依赖于互斥锁以确保线程安全,线程申请了互斥锁后,可以调用特定函数进入条件变量等待队列(同时释放互斥锁),其他线程则可以通过条件变量在特定的条件下唤醒该线程(唤醒后线程重新获得互斥锁),实现线程同步.
- 例如一个线程访问队列时,发现队列为空,则它只能等待其它线程将数据添加到队列中,这种情况就需要用到条件变量.
- 线程同步的概念:在保证数据安全的前提下,让线程能够按照某种特定的顺序访问共享资源,从而有效避免线程饥饿问题(饥饿问题指线程长时间等待资源而无法被调度).

pthread线程库提供的条件变量操作
//声明全局互斥锁并初始化
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//声明全局条件变量并初始化
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
- 线程等待条件:
任务线程代码{pthread_mutex_lock(&mutex);if(条件为假)pthread_cond_wait(&cond, &mutex);//等待时会释放互斥锁,等待完后自动加锁//访问共享资源....pthread_mutex_unlock(&mutex);
}
线程调用
pthread_cond_wait等待时,该接口会释放互斥锁,等待结束后自动加锁
- 控制线程给条件变量发送唤醒信号
控制线程代码{if(满足唤醒条件){pthread_mutex_lock(&mutex);pthread_cond_signal(cond);pthread_mutex_unlock(&mutex);}
}
唤醒操作加锁是为了避免信号丢失
- 示例:
#include <iostream>
#include <unistd.h>
#include <pthread.h>int cnt = 0;
//声明全局互斥锁并初始化
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//声明全局条件变量并初始化
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;void *Count(void * args)
{//线程分离,无需主线程等待pthread_detach(pthread_self());uint64_t number = (uint64_t)args;std::cout << "pthread: " << number << " create success" << std::endl;while(true){pthread_mutex_lock(&mutex);pthread_cond_wait(&cond, &mutex); std::cout << "pthread: " << number << " , cnt: " << cnt++ << std::endl;pthread_mutex_unlock(&mutex);}
}int main()
{for(uint64_t i = 0; i < 4; i++){pthread_t tid;pthread_create(&tid, nullptr, Count, (void*)i);usleep(1000);}sleep(3);std::cout << "main thread ctrl begin: " << std::endl;while(true) {sleep(1);//唤醒在cond的等待队列中等待的一个线程,默认都是第一个pthread_mutex_lock(&mutex);pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex);//按顺序唤醒在cond的等待队列中的所有线程//pthread_cond_broadcast(&cond);std::cout << "signal one thread..." << std::endl;}return 0;
}
- 线程同步过程图解:



- 条件变量和锁的销毁:
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
二.生产者消费者模型
- 生产者消费者模型是一种多线程并发协作的设计框架,生产者负责生成并发送数据,消费者负责接收并处理数据.
- 生产者和消费者之间存在一个数据容器作为缓冲区,生产者生产的数据存入容器中,消费者需要的数据从容器中获取,实现了生产者和消费者之间的数据传输解耦
- 数据容器由互斥锁保护,同一个时刻只能有一个线程访问数据容器,生产者和消费者之间通过条件变量(或信号量)实现同步
- 对于数据容器的访问,生产者和消费者遵循三个原则:
- 生产者和生产者之间互斥
- 消费者和消费者之间互斥
- 生产者和消费者之间互斥并同步

生产者消费者模型的高效性
- 由于生产者和消费者之间的数据传输解耦,生产者生产完数据之后不用等待消费者处理数据,而是直接将数据存入容器,消费者不需要向生产者请求数据,而是直接从容器里获取数据,因此即便在生产者和消费者的效率不对等且多变的情况下,多个生产者依然可以高效专一地并发生产数据,多个消费者依然可以高效专一地并发处理数据,使得系统整体的并发量得到提高

基于环形队列实现生产者消费者模型中的数据容器
- 环形队列中,消费者访问队列的头指针进行数据出队操作,生产者访问队列的尾指针进行数据入队操作
- 两把互斥锁分别保证消费者和消费者之间的互斥以及生产者和生产者之间的互斥,两个信号量实现消费者和生产者之间的互斥与同步



- 当环形队列既不为空也不为满时,支持一个生产者和一个消费者并发地进行数据的存取
#pragma once
#include <iostream>
#include <vector>
#include <semaphore.h>
#include <pthread.h>//环形队列默认容量
const static int defaultcap = 5;template<class T>
class RingQueue{
private:std::vector<T> ringqueue_;int cap_; //容器的容量int c_step_; // 消费者环形队列指针int p_step_; // 生产者环形队列指针sem_t cdata_sem_; // 消费者的数据资源sem_t pspace_sem_; // 生产者的空间资源pthread_mutex_t c_mutex_; //消费者与消费者之间的互斥锁pthread_mutex_t p_mutex_; //生产者与生产者之间的互斥锁
public:RingQueue(int cap = defaultcap):ringqueue_(cap), cap_(cap), c_step_(0), p_step_(0){//初始化生产者和消费者的信号量-->消费者一开始没有信号量资源,生产者一开始具有最多的空间资源sem_init(&cdata_sem_, 0, 0);sem_init(&pspace_sem_, 0, cap);pthread_mutex_init(&c_mutex_, nullptr);pthread_mutex_init(&p_mutex_, nullptr);}~RingQueue(){sem_destroy(&cdata_sem_);sem_destroy(&pspace_sem_);pthread_mutex_destroy(&c_mutex_);pthread_mutex_destroy(&p_mutex_);}//信号量的资源状态可以区分队列的空和满void Push(const T &in) {//生产者等待空间资源sem_wait(&pspace_sem_);pthread_mutex_lock(&p_mutex_);ringqueue_[p_step_] = in;p_step_++;p_step_ %= cap_;pthread_mutex_unlock(&p_mutex_);//生产完数据后增加消费者的信号量资源sem_post(&cdata_sem_);}void Pop(T *out) {//消费者等待数据资源sem_wait(&cdata_sem_);pthread_mutex_lock(&c_mutex_);*out = ringqueue_[c_step_];c_step_++;c_step_ %= cap_;pthread_mutex_unlock(&c_mutex_);//消费完数据后增加生产者的信号量资源sem_post(&pspace_sem_);}
};

相关文章:
线程同步--生产者消费者模型
文章目录 一.条件变量pthread线程库提供的条件变量操作 二.生产者消费者模型生产者消费者模型的高效性基于环形队列实现生产者消费者模型中的数据容器 一.条件变量 条件变量是线程间共享的全局变量,线程间可以通过条件变量进行同步控制条件变量的使用必须依赖于互斥锁以确保线…...
React hook+AntD pro实现Form表单的二次封装
React hookAntD pro实现Form表单的二次封装 封装Form表单1、在src/types下新建 antd/form/index.ts,进行Form表的配置、数据等类型的限制2、在 根目录/components 下新建 BaseForm/index.tsx文件3、在BaseForm/createFormIpt.tsx中,抽取对不同类型的表单…...
python异步切片下载文件(内置redis获取任务 mongo更新任务状态等)
异步切片下载二进制文件并上传桶删除本地文件 import json import os import asyncio from urllib import parseimport aiohttp import aioredis from motor.motor_asyncio import AsyncIOMotorClient from retrying import retry from minio import Minio from minio.error im…...
《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(10)-Fiddler如何设置捕获Firefox浏览器的Https会话
1.简介 经过上一篇对Fiddler的配置后,绝大多数的Https的会话,我们可以成功捕获抓取到,但是有些版本的Firefox浏览器仍然是捕获不到其的Https会话,需要我们更进一步的配置才能捕获到会话进行抓包。 2.宏哥环境 1.宏哥的环境是Wi…...
阿里云云原生弹性方案:用弹性解决集群资源利用率难题
作者:赫曦 随着上云的认知更加普遍,我们发现除了以往占大部分的互联网类型的客户,一些传统的企业,一些制造类的和工业型企业客户也都开始使用云原生的方式去做 IT 架构的转型,提高集群资源使用率也成为企业上云的一致…...
Spring-BeanPostProcessor PostConstruct init InitializingBean 执行顺序
执行顺序探究 新建一个对象用于测试 Component public class Student implements InitializingBean {private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name name;}public int getAge() {return age;}pu…...
【算法】递归
递归 递归初始递归:数列求和递归的应用:任意进制转换递归深度限制递归可视化:分形树递归可视化:谢尔宾斯基Sierpinski三角形递归的应用:汉诺塔递归的应用:探索迷宫 分治策略和递归优化问题兑换最少个数硬币…...
DC-1靶机刷题记录
靶机下载地址: 链接:https://pan.baidu.com/s/1GX7qOamdNx01622EYUBSow?pwd9nyo 提取码:9nyo 参考答案: https://c3ting.com/archives/kai-qi-vulnhnbshua-tiDC-1.pdf【【基础向】超详解vulnhub靶场DC-1】 https://www.bilibi…...
rust跟我学七:获取外网IP地址
图为RUST吉祥物 大家好,我是get_local_info作者带剑书生,这里用一篇文章讲解get_local_info是怎么获取到本机的外网IP地址。 首先,先要了解get_local_info是什么? get_local_info是一个获取linux系统信息的rust三方库,并提供一些常用功能,目前版本0.2.4。详细介绍地址:[…...
华为:交换机忘记console密码重置
一、背景 许多旧项目经过长时间使用后,因为没有特定的管理运维人员,初始对接人也将初始账号密码等重要信息丢失,现需要进后台查看配置或更改网络配置,需重置密码 二、重置密码,不重置设备方法 1、使用console插入交…...
2024年甘肃省职业院校技能大赛信息安全管理与评估 样题三 模块一
竞赛需要完成三个阶段的任务,分别完成三个模块,总分共计 1000分。三个模块内容和分值分别是: 1.第一阶段:模块一 网络平台搭建与设备安全防护(180 分钟,300 分)。 2.第二阶段:模块二…...
Go 中 slice 的 In 功能实现探索
文章目录 遍历二分查找map key性能总结 之前在知乎看到一个问题:为什么 Golang 没有像 Python 中 in 一样的功能?于是,搜了下这个问题,发现还是有不少人有这样的疑问。 补充:本文写于 2019 年。GO 现在已经支持泛型&am…...
pyDAL一个python的ORM(终) pyDAL的一些性能优化
一、大批量插入数据 对于 大量数据插入时,虽然pyDAL也手册中有个方法:bulk_insert(),但是手册也说了,虽然方法上是一次可以多条数据,如果后端数据库是关系型数据库,他转换为SQL时它是一条一条的插入的&…...
springboot log4j配置xml实例说明
提供样本配置代码 xml <?xml version"1.0" encoding"UTF-8"?> <!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL --> <!-- status log4j2内部日志级别 --> <configurat…...
VsCode重新安装需要配机的ESLint和 Prettier - Code formatter 配置
新电脑安装完Vscode后,需要装几个插件,这里记录下: {"diffEditor.ignoreTrimWhitespace": false,"files.autoSave": "afterDelay","editor.codeActionsOnSave": {"source.fixAll.eslint"…...
录屏功能怎么打开?简单操作,一学就会!
录屏功能在当今互联网时代变得越来越重要,无论是游戏录制、在线课程录制还是屏幕操作演示,录屏功能都为我们提供了便捷的解决方案。可是您知道录屏功能怎么打开吗?接下来,让我们一起探索如何在电脑上开启录屏功能,记录…...
小程序显示兼容处理,home键处理
定义: env(safe-area-inset-bottom)和env(safe-area-inset-top)是CSS中的变量,用于获取设备底部和顶部安全区域的大小 示例: padding-bottom: calc(env(safe-area-inset-bottom) 12px); /* 兼容iOS> 11.2 */安全间距类型: …...
【java八股文】之JVM基础篇
【java八股文】之JVM基础篇-CSDN博客 【java八股文】之MYSQL基础篇-CSDN博客 【java八股文】之Redis基础篇-CSDN博客 【java八股文】之Spring系列篇-CSDN博客 【java八股文】之分布式系列篇-CSDN博客 【java八股文】之多线程篇-CSDN博客 【java八股文】之JVM基础篇-CSDN博…...
2024美赛数学建模思路 - 案例:异常检测
文章目录 赛题思路一、简介 -- 关于异常检测异常检测监督学习 二、异常检测算法2. 箱线图分析3. 基于距离/密度4. 基于划分思想 建模资料 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 一、简介 – 关于异常…...
【EI会议征稿通知】2024年通信技术与软件工程国际学术会议 (CTSE 2024)
2024年通信技术与软件工程国际学术会议 (CTSE 2024) 2024 International Conference on Communication Technology and Software Engineering (CTSE 2024) 2024年通信技术与软件工程国际学术会议 (CTSE 2024)将于2024年03月15-17日在中国长沙举行。会议专注于通信技术与软件工…...
告别Elsevier投稿焦虑:Elsevier Tracker的智能监控方案
告别Elsevier投稿焦虑:Elsevier Tracker的智能监控方案 【免费下载链接】Elsevier-Tracker 项目地址: https://gitcode.com/gh_mirrors/el/Elsevier-Tracker 作为科研工作者,你是否也曾经历过这样的困境:每天多次登录Elsevier投稿系统…...
Llama-3.2V-11B-cot效果展示:漫画分镜连续性与叙事逻辑分析
Llama-3.2V-11B-cot效果展示:漫画分镜连续性与叙事逻辑分析 1. 模型能力概览 Llama-3.2V-11B-cot是基于Meta多模态大模型开发的专业级视觉推理工具,特别针对漫画分镜分析与叙事逻辑理解进行了深度优化。该模型在双卡4090环境下展现出强大的视觉推理能力…...
B站视频转文字:如何用AI技术轻松提取视频内容?
B站视频转文字:如何用AI技术轻松提取视频内容? 【免费下载链接】bili2text Bilibili视频转文字,一步到位,输入链接即可使用 项目地址: https://gitcode.com/gh_mirrors/bi/bili2text 在信息爆炸的时代,视频已成…...
MelonLoader Cpp2IL组件加载故障解决方案:从排查到优化
MelonLoader Cpp2IL组件加载故障解决方案:从排查到优化 【免费下载链接】MelonLoader The Worlds First Universal Mod Loader for Unity Games compatible with both Il2Cpp and Mono 项目地址: https://gitcode.com/gh_mirrors/me/MelonLoader 问题现象&am…...
Navicat重置工具终极指南:macOS用户免费解锁专业功能的完整方案
Navicat重置工具终极指南:macOS用户免费解锁专业功能的完整方案 【免费下载链接】navicat_reset_mac navicat mac版无限重置试用期脚本 Navicat Mac Version Unlimited Trial Reset Script 项目地址: https://gitcode.com/gh_mirrors/na/navicat_reset_mac 还…...
【车辆】插电式混合动力汽车(PHEV)动力系统进行建模与设计MATLAB 代码,含发动机、电机、电池组等组件
✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。👇 关注我领取海量matlab电子书和数学建模资料🍊个人信条:格物致知,完整Matl…...
基于 MySQL+MHA+Keepalived 搭建高可用主从集群实战
一、方案背景与技术选型1.1 为什么需要 MySQL 高可用在生产环境中,数据库是业务系统的核心基石,一旦 MySQL 服务出现宕机、主库故障等问题,会直接导致业务中断、数据丢失,给企业带来不可估量的损失。因此,搭建一套高可…...
终极指南:Android AdvancedRecyclerView 低版本兼容处理与 API 14+适配方案
终极指南:Android AdvancedRecyclerView 低版本兼容处理与 API 14适配方案 【免费下载链接】android-advancedrecyclerview RecyclerView extension library which provides advanced features. (ex. Googles Inbox app like swiping, Play Music app like drag and…...
终极指南:Windows游戏控制器虚拟驱动ViGEmBus完全掌握
终极指南:Windows游戏控制器虚拟驱动ViGEmBus完全掌握 【免费下载链接】ViGEmBus Windows kernel-mode driver emulating well-known USB game controllers. 项目地址: https://gitcode.com/gh_mirrors/vi/ViGEmBus ViGEmBus是一款强大的Windows内核模式驱动…...
别再忍受小窗口了!手把手教你给Ubuntu虚拟机装VMware Tools实现完美全屏
告别局促视界:Ubuntu虚拟机全屏显示的终极解决方案 第一次在VMware里启动Ubuntu时,那个缩在屏幕一角的小窗口简直像被关在笼子里的鸟——明明有广阔的显示空间,却只能蜷缩着操作。拖动文件得来回滚动,阅读文档要不断放大ÿ…...
