【Linux 多线程同步】使用同步和互斥实现生产消费模型
目录
1.同步的接口
2.多线程但是按顺序来执行
3.生产消费模型
4.使用互斥加同步实现生产消费模型 (采用环形队列)
同步:在保证数据安全的前提下,让线程能够按照某种特定的顺序访问临界资源,从而有效避免饥饿问题
1.同步的接口
pthread_cond_t 是条件变量;
2.多线程但是按顺序来执行
- 保证了每个线程都被执行,没有饥饿问题
#include<iostream>
#include<pthread.h>
#include<unistd.h>
using namespace std;pthread_cond_t cond;//条件变量
pthread_mutex_t mtx;
void* Work(void* args)
{int num=*((int*)args);delete (int*)args;while(1){pthread_cond_wait(&cond,&mtx);cout<<"worker: "<<num<<endl;}
}
void* Control(void* args)
{while(1){pthread_cond_signal(&cond);sleep(1);}
}
int main()
{//初始化条件变量和互斥锁pthread_cond_init(&cond,NULL);pthread_mutex_init(&mtx,NULL);pthread_t master;pthread_t worker[5];for(int i=0;i<5;i++){//5个轻量级进程int* tmp=new int(i);pthread_create(worker+i,NULL,Work,(void*)tmp);}pthread_create(&master,NULL,Control,NULL);//使用同步管理另外5个轻量级进程按特定顺序执行//等待轻量级进程for(int i=0;i<5;i++){pthread_join(worker[i],NULL);}//释放条件变量和互斥锁pthread_join(master,NULL);pthread_cond_destroy(&cond);return 0;
}
执行结果:

3.生产消费模型

4.使用互斥加同步实现生产消费模型 (采用环形队列)
条件变量判断应采用while而不是if,线程被挂起其他,线程可能会修改临界资源,pthread_cond_signal唤醒线程可能条件不再满足;
if(判断条件)//不完全正确的{pthread_cond_wait(&_cond,&_mtx);}
while(判断条件)//正确{pthread_cond_wait(&_cond,&_mtx);}
BlockQueue.hpp
#pragma once
#include<iostream>
#include<queue>
#include<pthread.h>#define CAPACITY 10namespace ds_blockqueue{template<class T>class BlockQueue{private:std::queue<T> bq;//先入先出队列int cap;//容量//两个条件变量和一个互斥锁pthread_cond_t pc;pthread_cond_t cc;pthread_mutex_t mtx;public:BlockQueue():cap(CAPACITY){pthread_cond_init(&pc,nullptr);pthread_cond_init(&cc,nullptr);pthread_mutex_init(&mtx,nullptr);}~BlockQueue(){pthread_cond_destroy(&pc);pthread_cond_destroy(&cc);pthread_mutex_destroy(&mtx);}private:void WaitProducer(){pthread_cond_wait(&pc,&mtx);}void WaitConsumer(){pthread_cond_wait(&cc,&mtx);}void WakeupProducer(){pthread_cond_signal(&pc);}void WakeupConsumer(){pthread_cond_signal(&cc);}void Lock(){pthread_mutex_lock(&mtx);}void Unlock(){pthread_mutex_unlock(&mtx);}private:bool IsFull(){return bq.size()==cap;}bool IsEmpty(){return bq.size()==0;}public://当满时生产者需要等待消费者消费//当空时消费者需要等待生产者生产void Push(const T& in){Lock();while(IsFull())//被挂起如果其他轻量级进程修改临界资源,使用if判断这个条件条件不一定是满足的使用while免得伪唤醒{WaitProducer();}bq.push(in);//生成一个就可以消费了//if(bq.size()>=cap/2)WakeupConsumer(); Unlock();}void Pop(T* out){Lock();while(IsEmpty())//被挂起如果其他轻量级进程修改临界资源,使用if判断这个条件条件不一定是满足的使用while免得伪唤醒{WaitConsumer();}*out=bq.front();bq.pop();//消费一个就可以生产了//if(bq.size()<=cap/2)WakeupProducer();Unlock();}};
}
cp_test.cc
#include "BlockQueue.hpp"
#include "Task.hpp"
#include<unistd.h>
#include<cstdlib>
#include<time.h>
using namespace ds_blockqueue;
using namespace ds_task;const char* op="+-*/";
void* Consumer(void* args)
{BlockQueue<Task>* bq=(BlockQueue<Task>*)args;while(true){Task t;int data=0;bq->Pop(&t);std::cout<<"消费数据:";t();sleep(1);}
}
void* Producer(void* args)
{BlockQueue<Task>* bq=(BlockQueue<Task>*)args;while(true){int x=rand()%20+1;int y=rand()%20+1;char tmp=op[rand()%4];Task t(x,y,tmp);// //制造数据// int data=rand()%10+1;//std::cout<<"生产数据:"<<data<<std::endl;std::cout<<"生产数据:"<<x<<tmp<<y<<std::endl;bq->Push(t);sleep(2);}
}
int main()
{srand((long long)time(nullptr));BlockQueue<Task>* bq=new BlockQueue<Task>;//创建阻塞队列pthread_t pid1;pthread_t pid2;//创建消费者和生产者pthread_create(&pid1,nullptr,Consumer,(void*)bq);pthread_create(&pid2,nullptr,Producer,(void*)bq);pthread_join(pid1,nullptr);pthread_join(pid2,nullptr);return 0;
}
Task.hpp:处理数据
#include<iostream>namespace ds_task{class Task{private:int _x;int _y;char _op;public:Task(){}Task(const int& x,const int& y,const char& op) :_x(x),_y(y),_op(op) {}~Task(){}void operator()(){int tatol=0;switch(_op){case '+':tatol=_x+_y;break;case '-':tatol=_x-_y;break;case '*':tatol=_x*_y;break;case '/':tatol=_x/_y;break;default:break;}std::cout<<_x<<_op<<_y<<"="<<tatol<<std::endl;}};
}
执行结果:

相关文章:
【Linux 多线程同步】使用同步和互斥实现生产消费模型
目录 1.同步的接口 2.多线程但是按顺序来执行 3.生产消费模型 4.使用互斥加同步实现生产消费模型 (采用环形队列) 同步:在保证数据安全的前提下,让线程能够按照某种特定的顺序访问临界资源,从而有效避免饥饿问题 …...
【TypeScript】TypeScript的接口和对象类型(interface):
文章目录一、使用接口约束的时候不能多一个属性也不能少一个属二、重名interface 可以合并,继承三、可选属性 使用?操作符四、任意属性 [propName: string]五、只读属性 readonly,是不允许被赋值的只能读取六、添加函数一、使用接口约束的时候不能多一个…...
7、函数与异常
目录一、函数的概念二、匿名函数三、闭包四、defer五、异常机制一、函数的概念 函数的基本形式 //函数定义。a,b是形参 func argf(a int, b int) { a a b } var x, y int 3, 6 argf(x, y) //函数调用。x,y是实参函数参数: func arg2(a, b int) { //参数类型相…...
Julia 语言环境安装
Julia 语言支持以下系统: LinuxFreeBSDmacOSWindowsAndroid Julia 安装包下载地址为:Download Julia。 Github 源码地址:GitHub - JuliaLang/julia: The Julia Programming Language。 国内镜像地址:Index of /julia-releases/…...
5.1 线程
文章目录1.概述2.多线程的特性2.1 随机性2.2 CPU分时调度2.3 线程的状态2.4 线程状态与代码对照3.多线程代码实现方式1:继承Thread3.1 概述3.2 常用方法3.3 测试多线程的创建方式14.多线程代码实现方式2:实现Runnable接口4.1 概述4.2 常用方法4.3 练习2:测试多线程的…...
通讯录的实现
一、目的:使用C实现通讯录二、包含功能:添加联系人:向通讯录中添加新人,信息包括(姓名、性别、年龄、联系电话、家庭住址)最多记录1000人显示联系人:显示通讯录中所有联系人信息删除联系人:按照姓名进行删除指定联系人…...
Urho3D导航
Urho3D通过使用Recast和Detour库实现导航网格生成和路径查找。 导航功能通过NavigationMesh和Navigable组件公开。 NavigationMesh从已使用Navigable组件标记的子节点收集几何体。默认情况下,可导航组件的行为是递归的:除非禁用递归,否则也…...
【学习总结】激光雷达与相机外参标定:代码(cam_lidar_calibration)
前段时间尝试了一款激光雷达和相机标定的代码,总结了博客: 【学习总结】激光雷达与相机外参标定:原理与代码 但总觉得那个代码太差劲,而且精度不行,于是又找了些新的代码,体验比之前的好很多,在…...
车载技术开发—{Android CarFrameWork}
Android Automotive平台 Android Automotive是通过Android的通用框架,语言和API来实现的一个全栈,开源,高度可定制的平台。 Android Automotive与整个Android生态系统的关系 Android Automotive是Android的一部分。 Android Automotive不是…...
多城市二手车买卖发布管理小程序开发
多城市二手车买卖发布管理小程序开发 功能特性: 为你介绍二手车微信小程序的功能特性。 车辆分类搜索,支持按品牌、售价、年龄、上牌时间、排量等筛选。 车源发布,支持用户一键发布二手车,平台审核上线,发布可编辑、删除等操作。…...
企业级信息系统开发学习笔记1.2 初探Spring——利用组件注解符精简Spring配置文件
文章目录零、本讲学习目标一、课程引入二、打开项目 - SpringDemo三、利用组件注解符精简Spring配置文件(一)创建新包(二)复制四个类(三)修改杀龙任务类(四)修改救美任务类ÿ…...
37、基于51单片机乒乓球比赛系统设计
摘要 乒乓球游戏电路是一个对输入信号、输入时机正确与否的8个LED表示乒乓球球台和乒乓球,用数码管模拟显示器,显示比赛局数比分和每局玩家得分的电路。电路并不复杂,整体分为两个模块:一,游戏主模块;二&a…...
VMware虚拟机安装Win11最详细过程以及遇到的这台电脑无法运行Windows11的问题
准备工作 在使用VMware虚拟机安装Win11之前我们先把准备工作做好,以免后续思绪混乱导致出错。 1. 到VMware官网或点击链接下载正版VMware Workstation 16 Pro。 2. 双击打开安装包,点击下一步。 3. 阅读用户许可协议,勾选我接受许可协议中的…...
centos误删python2后怎么重新安装
此教程为离线安装 一. 先查询系统版本 cat /proc/version Linux version 3.10.0-1127.el7.x86_64 (mockbuildkbuilder.bsys.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) ) #1 SMP Tue Mar 31 23:36:51 UTC 2020 二. 安装python2.7.5(已知原python版…...
Qt 开发使用VSCode 笔记2
在之前有写过使用VSCode开发QT的笔记 Qt 开发使用VSCode 在以前的基础上继续学习记录写下《Qt 开发使用VSCode 笔记2》 该笔记相比之前的Qt 开发使用VSCode新加了如下内容: 工作区的使用使用Natvis进行Qt感知对象可视化通过vscode创建QT Quick项目 工作区的使用 …...
查找算法复习
先序在了解查找算法之前,需要熟悉几个概念,不然后面容易产生理解错误。查找表:即被查找的对象,通常由几个关键字组成。关键字:就是数据项、字段的意思。关键字有主次之分,其中主关键字取值是唯一的。查找长…...
腾讯前端必会面试题(必备)
如何提取高度嵌套的对象里的指定属性? 有时会遇到一些嵌套程度非常深的对象: const school {classes: {stu: {name: Bob,age: 24,}} }像此处的 name 这个变量,嵌套了四层,此时如果仍然尝试老方法来提取它: const {…...
探访上汽通用武汉奥特能超级工厂
上汽通用汽车在电动化和智能网联化新技术领域投入了700亿大洋,武汉奥特能超级工厂就是其中一个重点项目。这个工厂已经投产,将成为上汽通用汽车的新能源生产基地,加速奥特能平台车型的推出。 最近别克推出了Electra E5,它是别克第…...
【Linux】线程函数和线程同步详细整理(金针菇般细)
目录 一,线程函数 1.获取当前线程ID 2.创建线程 3.退出线程 4.阻塞线程 5.分离线程 6.取消线程 7.线程比较 8.测试代码(线程函数总结) 二,线程同步 1.互斥锁 2.读写锁 3.条件变量 4.信号量 一,线程函数 …...
Python学习笔记6:抽象
抽象 函数 判断某个对象是否可调用,可使用内置函数callable >>> import math >>> x 1 >>> y math.sqrt >>> callable(x) False >>> callable(y) True斐波那契数组 def fibs(num): result [0, 1] for i i…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...
多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...
计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...

