线程-条件变量和生产者消费者模型

这个内容比较重要,并且面试很容易被问道。所以把他单独拿出来了。

条件变量

条件变量是一种线程同步机制

  • 当条件不满足时,相关线程被一直阻塞,直到某种条件出现,这些线程才会被唤醒。
  • 为了保护共享资源,条件变量需要和互斥锁结合一起使用。
  • 比较常见的是生产/消费者模型(高速缓存队列)。

生产者消费者的示意图:
在这里插入图片描述
左边是生产这,右边是消费者,生产者先把需要处理的数据放在缓冲队列中,然后向消费者发出通知。消费者接到通知后,从缓存队列中把数据拿出来,然后处理他们。

一个生活中的例子:

某企业的售后服务系统,客服小姐姐负责收集用户需求。他们生成工单,然后派发给维修工人。在这个例子中,客服小姐姐是生产者,工单是数据的任务队列,维修工人是数据的消费者。

再来看一个实际开发中的例子:
在这里插入图片描述
假设这是一个网站的后台服务程序,大型网站的后台服务程序有明确的分工。网络通信的线程负责接收客户端的业务请求。然后把业务请求放入队列。后台工作线程负责处理业务请求。在实际开发中,生产者可以是一个线程。也可以是多个线程。而消费者一般是多个线程。这多个线程有一个通俗的名称叫线程池。
大家想想看。如果只用互斥锁。能实现生产者-消费者模型吗?
多个线程共享缓存队列。读写数据的时候可以用互斥锁来保护,但是当生产者把数据放入缓存队列后,如何通知消费者线程呢?互斥锁好像做不到。

条件变量是一种线程同步机制。当条件不满足时,相关线程被一直阻塞,直到某种条件出现,这些
线程才会被唤醒。
C++11的条件变量提供了两个类:

  • condition_variable:只支持与普通mutex搭配,效率更高。
  • condition_variable_any:是一种通用的条件变量,可以与任意mutex搭配(包括用户自定义的锁类型)。

对于代码生产者要做的事情就是:

  1. 生产数据
  2. 把数据放入缓冲队列
  3. 向消费者线程发出通知

消费者是一个死循环,就像工人一样,等待派单,处理工单,不断循环

#include<iostream>
#include<algorithm>
#include<string>
#include<mutex>
#include<deque>
#include<queue>
#include<condition_variable>
using namespace std;
class AA {mutex m_mutex;//互斥锁condition_variable m_cond;//条件变量queue<string, deque<string> > m_q;//缓冲队列,底层容器用deque
public:void incache(int num)//生产数据,num指定数据的个数{lock_guard<mutex> lock(m_mutex);//申请加锁for (int i = 0;i < num;i++) {static int bh = 1;//超女编号string message = to_string(bh++) + "号超女";//拼接出一个数据m_q.push(message);//把生产出来的数据入队 }m_cond.notify_one();//唤醒一个当前条件变量堵塞的线程 }void outcache() {//消费者线程任务函数while (true) {string message;//存放出队的数据{//这个作用域的作用是让他立刻释放锁,数据处理完出队之后立刻释放锁//把互斥锁转化成unique_lock<mutex>,并申请加锁unique_lock<mutex> lock(m_mutex);while (m_q.empty())//如果队列非空,不进入循环,之间处理数据,必须用循环,不能用if m_cond.wait(lock);//等待生产者的幻想信号//数据出队message = m_q.front();m_q.pop();}//处理出队的数据(把数据消费掉)this_thread::sleep_for(chrono::milliseconds(1));//假设处理数据需要1毫秒cout << "线程:" << this_thread::get_id() << "," << message << endl;}}};
int main() {AA aa;thread t1(&AA::outcache,&aa);//创建消费者线程t1thread t2(&AA::outcache, &aa);//创建消费者线程t1thread t3(&AA::outcache, &aa);//创建消费者线程t1this_thread::sleep_for(chrono::seconds(2));//休眠2秒aa.incache(3);//生产三个数据this_thread::sleep_for(chrono::seconds(2));//休眠3秒aa.incache(5);//生产三个数据t1.join();t2.join();t3.join();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2979804.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

ROM修改进阶教程------安卓7_____安卓13去除签名验证操作步骤解析

同类博文: 安卓玩机搞机技巧综合资源-----修改rom 制作rom 解包rom的一些问题解析【二十一】_qcn改区域锁-CSDN博客 安卓系列机型rom修改。如果你删减了系统相关的app。那么严重会导致开机系统卡米 定屏等问题。这类一般都是系统签名验证导致的。而破解签名验证一般都是修改…

JAVA:Kettle 强大的开源ETL工具

请关注微信公众号&#xff1a;拾荒的小海螺 1、简述 Kettle&#xff08;Pentaho Data Integration&#xff09;&#xff1a;强大的开源ETL工具Kettle&#xff0c;又称作Pentaho Data Integration&#xff0c;是一款流行的开源ETL&#xff08;Extract, Transform, Load&#x…

ubuntu如何运行python程序

打开LINUX UBUNTU操作系统。 找到左边的TERMINAL&#xff0c;打开窗口。 输入python&#xff0c;如果没有安装&#xff0c;就会提示需要安装。 如果已经安装好python3&#xff0c;直接输入&#xff0c;那么就会进入。 exit()就可以退出python3的模式。 创建一个文件&#xff0c…

有没有学网络空间安全的学长,想知道学长们毕业以后都去干嘛了?

我作为一个零基础小白到白帽黑客&#xff0c;也认识到了很多零基础小白的&#xff0c;有一些网络空间安全的学员&#xff0c;但是大多数还是非计算机相关专业的学员。他们通过系统学习网络安全&#xff0c;掌握黑客技术之后&#xff0c;都找到了自己满意的工作。 同学A&#x…

二叉树oj题(2)

1.二叉树的最近公共祖先 解题思路&#xff1a;方法一&#xff1a; 1.先判断p或者q 是不是 root当中的一个 2.左子树当中递归査找p或者q 3.右子树当中递归查找p或者q 如何查找: root 的 left 和 right 都不为空 ->root root的 left 为空 right 不为空->right这一侧找…

话题——为什么要学习程序,成为程序员呢?

选择成为一名程序员&#xff0c;这对我而言并非是一时冲动&#xff0c;而是深思熟虑后的坚定选择。在当下这个信息化、数字化的时代&#xff0c;程序员这一职业不仅具有极高的技术含量&#xff0c;更承载了推动社会进步、引领科技发展的重任。特别是在深度学习这一前沿领域&…

复写零 ---- 双指针

题目链接 题目: 分析: 就地对数组进行操作, 肯定是需要双指针的 那么我们从左往右进行复写, 定义一个cur用来遍历数组, 一个dest用来修改数组的值, 如果cur下标的值不为零, 那么将cur的值写到dest位置, cur, dest; 如果cur下标的值为0, 那么就将dest下标的值写为0, dest, 再将…

Linux系统编程——进程

一、进程相关概念 面试中关于进程&#xff0c;应该会问的的几个问题&#xff1a; 1.1 什么是程序&#xff1f;什么是进程&#xff1f;有什么区别&#xff1f; 程序是静态的概念&#xff0c;比如&#xff1a; 磁盘中生成的a.out文件&#xff0c;就叫做&#xff1a;程序 进程…

11408知识点集合

文章目录 一、数学(一) 高数0.初等数学补充1.函数、极限、连续2.导数3.中值定理4.积分5.微分方程6.空间解析几何7.多元微分8.重积分9.曲线曲面积分10.无穷级数11.其他杂记(二) 线代0.串联各章的等价条件1.行列式、矩阵的秩、矩阵的初等变换2.向量3.方程组、矩阵方程AXB4.特征值…

Springboot+Vue项目-基于Java+MySQL的学科竞赛管理系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

Kibana安装部署(Linux)

Kibana是Elasticsearch的开源可视化工具&#xff0c;与存储在Elasticsearch中的数据进行交互。 1. 下载软件 这里使用的Elasticsearch的版本是7.12.0&#xff0c;所以kibana选择同样的7.12.0版本。 官网下载地址&#xff1a;https://www.elastic.co/cn/downloads/past-releas…

WEB攻防-ASP中间件IIS 短文件名探针安全漏洞

IIS短文件名探针安全漏洞是一个与IIS&#xff08;Internet Information Services&#xff09;服务相关的安全问题。该漏洞主要是由于HTTP请求中使用了旧DOS 8.3名称约定&#xff08;SFN&#xff09;的代字符&#xff08;〜&#xff09;波浪号&#xff0c;这使得远程攻击者有可能…

Xilinx FPGA BGA推荐设计规则和策略(二)

引言&#xff1a;上一篇介绍了BGA封装PCB层数估计、BGA焊盘设计、过孔设计、信号走线等内容&#xff0c;本文我们介绍下FPGA BGA封装电源管脚布线。 1. 概述 工程师必须在设计阶段早期评估功率需求&#xff0c;以确保有足够的层和面积为需要功率的BGA焊盘提供足够的功率。因为…

深入探索GDB:Linux下强大的调试神器

目录 一、GDB简介&#xff1a;源码级调试的基石 二、GDB基础操作&#xff1a;从入门到熟练 启动与基本命令 三、GDB进阶功能&#xff1a;解锁更深层次的调试能力 1. 回溯追踪&#xff1a;洞察调用栈 2. 动态内存检测&#xff1a;揪出内存问题 3. 条件断点与观察点&#…

web测试基础知识

目录 web系统的基础 web概念(worldwideweb) 网络结构 发展 架构 B/S C/S P2P 工作原理 静态页面 动态页面 web客户端技术 浏览器的核心--渲染引擎 web服务器端技术 web服务器 应用服务器 集群环境 数据库 案例-URL 协议类型 主机名 端口 IP地址 分类 …

从0到1实现RPC | 接入Apollo配置中心

一、代码实现 添加依赖 添加apollo客户端的依赖和spring配置相关依赖 添加监听器 通过实现ApplicationContextAware接口&#xff0c;获取Spring上下文。 使用ApolloConfigChangeListener注解监听命名空间rpc-demo-provider.yaml和默认的application.properties。 监听逻辑…

Bentley二次开发教程21-文件及模型管理-分组(NamedGroup)介绍

当我们需要对模型中的元素分组时&#xff0c;就需要使用NamedGroup功能&#xff0c;不同于单元&#xff0c;他们的元素并没有那么强的组合关系&#xff0c;同时&#xff0c;组与组之间可以实现嵌套&#xff0c;体现元素间的层级关系。 创建NamedGroup NamedGroup的创建流程为…

JAVA之Spring入门导读

目录 一.Spring是什么&#xff1f; 1.1Spring的简介 1.2 个人看法 2 Spring的深层次了解 2.1Spring的结构层次 2.1Spring的优点 学习路径&#xff1a; Spring技术链接地址Spring项目的创建和简单使用http://t.csdnimg.cn/u01URIOC&#xff08;Inversion of Control&…

Linux中文件描述符与重定向的深入探索

目录 1. 理解C语言的文件操作函数 2. 操作系统的文件操作接口 3. 文件描述符详解和其内核本质 4. 如何理解Linux下一切皆文件 5. Linux中的重定向 5.1 输出重定向 5.2 追加重定向 5.3 输入重定向 6. 结合文件描述符理解重定向 7.重定向的系统调用 在Linux操作系统中&a…

学习配置文件

1.yml的语法格式问题&#xff1a; 2.配置文件获取数据&#xff1a; Value方式&#xff1a; Environment&#xff1a; 获取自定义对象的方式&#xff1a; 设置get和set方法&#xff0c;还有toString方法。 3. 日志配置&#xff1a; logo的配置&#xff1a; 日志插件&#xff…