线程同步--生产者消费者模型
文章目录
- 一.条件变量
- 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日在中国长沙举行。会议专注于通信技术与软件工…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...

7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...

论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...