【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…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...
论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing
Muffin 论文 现有方法 CRADLE 和 LEMON,依赖模型推理阶段输出进行差分测试,但在训练阶段是不可行的,因为训练阶段直到最后才有固定输出,中间过程是不断变化的。API 库覆盖低,因为各个 API 都是在各种具体场景下使用。…...
pycharm 设置环境出错
pycharm 设置环境出错 pycharm 新建项目,设置虚拟环境,出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...

