Linux:通过线程互斥同步实现基于BlockingQueue的生产消费者模型

一、总体调度:主函数Main.cc

#include "BlockQueue.hpp"
#include "Thread.hpp"
#include <string>
#include <vector>
#include <functional>
#include <unistd.h>
#include <ctime>using namespace ThreadModule;
int a=10;
using Task = std::function<void()>;
using blockqueue_t=BlockQueue<Task>;void PrintHello()
{std::cout<<"hello world"<<std::endl;
}
void Consumer(blockqueue_t &bq)
{while(true){//1.从blockqueue取下来任务Task t;bq.Pop(&t);//pop完成后t中会保存任务//2.处理这个任务t();//消费者私有}
}
void Productor(blockqueue_t &bq)
{srand(time(nullptr)^pthread_self());int cnt=10;while(true){sleep(1);Task t=PrintHello;bq.Enqueue(t);}
}
//productor和consumer共用此函数
void StartComm(std::vector<Thread<blockqueue_t>> *threads,int num,blockqueue_t &bq,func_t<blockqueue_t> func)
{for(int i=0;i<num;i++){std::string name="thread-"+std::to_string(i+1);threads->emplace_back(func,bq,name);threads->back().Start();}
}//启动consumer
void StartConsumer(std::vector<Thread<blockqueue_t>> *thread,int num,blockqueue_t &bq)
{StartComm(thread,num,bq,Consumer);
}//启动productor
void StartProductor(std::vector<Thread<blockqueue_t>> *thread,int num,blockqueue_t& bq)
{StartComm(thread,num,bq,Productor);
}
void WaitAllThread(std::vector<Thread<blockqueue_t>> &threads)
{for (auto &thread : threads){thread.Join();}
}
int main()
{blockqueue_t *bq=new blockqueue_t(5);std::vector<Thread<blockqueue_t>> threads;StartConsumer(&threads,3,*bq);StartProductor(&threads,1,*bq);WaitAllThread(threads);return 0;
}

二、线程功能的封装:Thread.hpp

#ifndef __THREAD_HPP__
#define __THREAD_HPP__#include <iostream>
#include <string>
#include <unistd.h>
#include <functional>
#include <pthread.h>namespace ThreadModule
{template<typename T>using func_t=std::function<void(T&)>;template<typename T>class Thread{public:void Excute(){_func(_data);}public:Thread(func_t<T> func,T&data,const std::string& name="none-name"):_func(func),_data(data),_threadname(name),_stop(true){}static void* threadroutine(void* args)//static成员函数没有this{Thread<T> *self = static_cast<Thread<T> *>(args);self->Excute();return nullptr;}bool Start(){int n=pthread_create(&_tid,nullptr,threadroutine,this);//把this传给threadroutine让其完成调用if(!n){_stop=false;return true;}else{return false;}}void Detach(){if(!_stop){pthread_detach(_tid);}}void Join(){if(!_stop){pthread_join(_tid,nullptr);}}std::string name(){return _threadname;}void Stop(){_stop = true;}~Thread(){}private:pthread_t _tid;std::string _threadname;T& _data;//要传入所执行函数的参数func_t<T> _func;//线程要执行的函数bool _stop;};
}
#endif

三、临界区阻塞队列:BlockQueue

#ifndef __BLOCK_QUEUE_HPP__
#define __BLOCK_QUEUE_HPP__#include <iostream>
#include <string>
#include <queue>
#include <pthread.h>template <typename T>
class BlockQueue
{
private:bool IsFull(){return _block_queue.size()==_cap;}bool IsEmpty(){return _block_queue.empty();}
public:
BlockQueue(int cap):_cap(cap)
{_productor_wait_num=0;_consumer_wait_num=0;pthread_mutex_init(&_mutex,nullptr);pthread_cond_init(&_product_cond,nullptr);pthread_cond_init(&_consum_cond,nullptr);
}
void Enqueue(T& in)
{pthread_mutex_lock(&_mutex);while(IsFull())//保证代码的健壮性{// 生产线程去等待,是在临界区中休眠的!你现在还持有锁呢!!!// 1. pthread_cond_wait调用是: a. 让调用线程等待 b. 自动释放曾经持有的_mutex锁 c. 当条件满足,线程唤醒,pthread_cond_wait要求线性// 必须重新竞争_mutex锁,竞争成功,方可返回!!!// 之前:安全_productor_wait_num++;pthread_cond_wait(&_product_cond,&_mutex);//  只要等待,必定会有唤醒,唤醒的时候,就要继续从这个位置向下运行!!_productor_wait_num--;}//进行生产_block_queue.push(in);if(_consumer_wait_num > 0)pthread_cond_signal(&_consum_cond); // pthread_cond_broadcastpthread_mutex_unlock(&_mutex);
}
void Pop(T *out)
{pthread_mutex_lock(&_mutex);while(IsEmpty()){// 消费线程去等待,是在临界区中休眠的!你现在还持有锁呢!!!// 1. pthread_cond_wait调用是: a. 让调用进程等待 b. 自动释放曾经持有的_mutex锁_consumer_wait_num++;pthread_cond_wait(&_consum_cond, &_mutex);  // 伪唤醒_consumer_wait_num--;}//进行消费*out=_block_queue.front();//让main.cc的消费者拿到任务_block_queue.pop();//通知生产者生产if(_productor_wait_num>0)pthread_cond_signal(&_product_cond);pthread_mutex_unlock(&_mutex);
}
~BlockQueue()
{pthread_mutex_destroy(&_mutex);pthread_cond_destroy(&_product_cond);pthread_cond_destroy(&_consum_cond);}
private:std::queue<T> _block_queue;//阻塞队列,是被整体使用的int _cap;//总上限pthread_mutex_t _mutex;//保护_block_queue的锁pthread_cond_t _product_cond;//专门给生产者提供的条件变量pthread_cond_t _consum_cond;//专门给生产者提供的条件变量int _productor_wait_num;int _consumer_wait_num;};
#endif

四、Makefile

cp:Main.ccg++ -o $@ $^ -std=c++11 -lpthread
.PHONY:clean
clean:rm -f cp

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Seq2seq、编码器解码器神经网络

目录 一、Seq2seq 简介二、编码器三、解码器四、编码器-解码器的训练 遇到看不明白的地方&#xff0c;欢迎在评论中留言呐&#xff0c;一起讨论&#xff0c;一起进步&#xff01; 需掌握的前提知识&#xff1a; LSTM、词嵌入 本文参考&#xff1a;【官方双语】编码、解码神经网…

PasteCluster组件介绍(一款让你的.Net服务快速支持集群部署的中间件)

前言 PasteCluster是由.NET6.0编写的集群中间件&#xff0c;先已开源: PasteCluster.Gitee 在实际开发中&#xff0c;如果一个服务(比如api)是否支持集群部署&#xff0c;其实是由开发决定的&#xff01; 举个栗子 我们知道缓存&#xff0c;可以分几种方式&#xff0c;最简单的…

tkinter菜单栏

tkinter菜单栏 菜单栏效果代码 菜单栏 在 Tkinter 中&#xff0c;Menu 组件用于创建菜单栏、下拉菜单和上下文菜单&#xff0c;是构建图形用户界面&#xff08;GUI&#xff09;应用程序的常见需求。 效果 代码 import tkinter as tk from tkinter import messagebox# 创建主…

DAMA学习笔记(一)-数据管理

1.引言 数据管理(Data Management) 是为了 交付、 控制、 保护 并 提升 数据和信息资产的 价值 , 在其整个生命周期中制订 计划、 制度、 规程和实践 活动, 并 执行 和 监督 的过程。 数据管理专业人员(Data Management Professional) 是指 从事数据管理各方面的工作…

MySQL与PostgreSQL关键对比三(索引类型)

目录 索引类型 B-tree 索引 Hash 索引 Full-text 索引 GiST 索引 GIN 索引 BRIN 索引 索引创建示例 MySQL PostgreSQL 结论 以下SQL语句的执行如果需要开发工具支持&#xff0c;可以尝试使用SQLynx或Navicat来执行。 MySQL和PostgreSQL在索引方面有许多相似之处&am…

【C#线程设计】2:backgroundWorker

实现&#xff1a; &#xff08;1&#xff09;.控件&#xff1a;group Box&#xff0c;text Box&#xff0c;check Box&#xff0c;label&#xff0c;botton&#xff0c;richtextbox 控件拉取见&#xff1a;https://blog.csdn.net/m0_74749240/article/details/139409510?spm1…

mingw如何制作动态库附python调用

1.mingw和msvc g -fpic HelloWorld.cpp -shared -o test.dllg -L . -ltest .\test.cpp 注意-L后面的.挨不挨着都行&#xff0c;-l不需要-ltest.dll&#xff0c;只需要-ltest 2.dll.cpp extern "C" {__declspec(dllexport) int __stdcall add(int a, int b) {return…

吴恩达2022机器学习专项课程C2W3:2.25 理解方差和偏差(诊断方差偏差正则化偏差方案)

目录 引言名词替代影响模型偏差和方差的因素1.多项式阶数2.正则化参数 判断是否有高偏差或高方差1.方法一&#xff1a;建立性能基准水平2.方法二&#xff1a;建立学习曲线 总结 引言 机器学习系统开发的典型流程是从一个想法开始&#xff0c;然后训练模型。初次训练的结果通常…

C语言最终讲:预处理详解

C语言最终讲&#xff1a;预处理详解 1.预定义符号2.#define定义常量3.#define定义宏4.带有副作用的宏参数5.宏替换的规则6.宏和函数的对比6.1宏的优势6.1.1\符号 6.2宏的劣势 7.#和##7.1#运算符7.2##运算符 8.命名约定9.#undef10.命令行定义11.条件编译12.头文件的包含12.1本地…

13. UDP协议与RTP协议

UDP协议 UDP协议比较简单&#xff1a; UDP的长度是固定的&#xff0c;用总长度-UDP长度就是数据长度。 UDP是不保证他的有序性和可靠性的。对于音频和视频是这样是比较好的&#xff0c;因为这段丢了&#xff0c;我们可以从下一段在开始解码。 RTP RTP 协议概述 RTP&#x…

【MySQL】(基础篇六) —— 过滤数据

过滤数据 本文将讲授如何使用SELECT语句的WHERE子句指定搜索条件。 WHERE子句 数据库表一般包含大量的数据&#xff0c;很少需要检索表中所有行。通常只会根据特定操作或需要提取表数据的子集。只检索所需数据需要指定搜索条件&#xff08;search criteria&#xff09;&…

独孤思维:做副业,万物皆可成为素材

01 分享一个独孤日更的素材来源。 很多小伙伴&#xff0c;刚开始写自媒体&#xff0c;都喜欢一本正经的阅读书籍&#xff0c;文章。 把素材来源&#xff0c;灵感来源&#xff0c;全部押注在这个地方。 其实万物皆可成为素材。 比如昨天早上&#xff0c;独孤参加公司的会议…

代码随想录算法训练营第36期DAY56

DAY56 套磁很顺利&#xff0c;发现又有书读了&#xff01; 300最长递增子序列 朴素法&#xff0c;这个好想&#xff0c;但是不对&#xff0c;比如 0 1 0 3 2 3 我的算法会找出0 1 3作为答案&#xff0c;而不是0 1 2 3 可以看出&#xff0c;后面的状态依赖于前面的状态&am…

zero shot,few shot以及无监督学习之间的关系是什么

Zero-shot learning、few-shot learning和无监督学习都是机器学习中的方法&#xff0c;它们共同的特点是在有限或没有标签数据的情况下进行学习。下面是这三种方法之间的关系和区别&#xff1a; Zero-shot Learning (零样本学习)&#xff1a; 零样本学习是在模型训练过程中完全…

中介子方程十

X$XFX$XEXyXαXiX$XαXiXrXkXtXyX$XpX$XyXtXkXrXiXαX$XiXαXyXEX$XFX$XEXyXαXiX$XαXiXrXkXtXyX$XpX$XyXtXkXrXiXαX$XiXαXyXEX$XαXηXtXαX$XWXyX$XyXWX$XpXαXqXηX$XeXαXhX$XdX$XpX$XdX$XyXeXαX$XEXyXαXiX$XαXiXrXkXtXyX$XpX$XyXtXkXrXiXαX$XiXαXyXEX$XαXeXyX$Xd…

Facebook革新:数字社交的下一个阶段

在数字化时代&#xff0c;社交网络已经成为人们生活中不可或缺的一部分。作为全球最大的社交网络平台之一&#xff0c;Facebook一直在不断创新&#xff0c;引领着数字社交的发展。然而&#xff0c;随着科技的不断进步和社交需求的变化&#xff0c;Facebook正在走向一个新的阶段…

Gitte的使用(Windows/Linux)

Gitte的使用&#xff08;Windows/Linux&#xff09; 一、Windows上使用Gitte1.下载程序2.在Gitte上创建远程仓库3.连接远程仓库4.推送文件到远程仓库 二、Linux上使用Gitte1.第一次从仓库上传1.1生成公钥1.2配置SSH公钥1.3新建一个仓库1.4配置用户名和邮箱在Linux中1.5创建仓库…

python字典应用

""" 字典应用 字典中保存了股票信息&#xff0c;完成下面的操作 1.找出股票价格大于100元的股票并创建一个新的字典 2、找出价格最高和最低的股票对应的股票代码 3.按照股票价格从高到低给股票代码排序 """stocks {AAPL: 191.88,G00G: 1186.96,…

强烈推荐 Setapp 上的 Mac 优质软件

Setapp 一款专为 macOS 设计的软件订阅平台&#xff0c;目前提供高达 240 款精心筛选的高品质应用程序&#xff0c;只需每月 9.9 美元的订阅费&#xff0c;即可畅享所有正版软件的使用权。让使用者无忧享受正版软件的稳定性和安全性&#xff0c;彻底告别盗版软件可能引发的风险…

Linux学习问题

遇到的第一个问题&#xff0c;FinalShell连接Centos7后&#xff0c;就连不上网&#xff0c;Centos7联网后就连不上FinalShell 解决方法&#xff0c;虚拟网卡上的ip地址不能和虚拟机ip地址一样 从这得到的解决方法