【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…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...

