当前位置: 首页 > news >正文

创建线程池和封装锁

封装一个锁

1.封装一个Mutex

class Mutex{public:Mutex(pthread_mutex_t * lock):_lock(lock){}void Lock(){pthread_mutex_lock(_lock);}void unLock(){pthread_mutex_unlock(_lock);}~Mutex(){}private:pthread_mutex_t *_lock;
};

2.封装一个LockGuard

class LockGuard{public:LockGuard(pthread_mutex_t * lock):_mutex(lock){_mutex.Lock();}~LockGuard(){_mutex.unLock();}private:Mutex _mutex;
};

在底层就可以直接创建一个LockGuard对象,就可以直接对临时资源进行加锁

类似:

​
{LockGuard(&mutex);//临界资源}​

创建线程池

封装线程

1.成员变量

private:std::string _threadname;pthread_t _pid;func_t<T> _func;bool _isrunning;T _data;
template <class T>
using func_t = std::function<void(T&)>;

我们创建一个fun_t 用来传递一个函数给线程,在内部用来回调。

2.构造函数

  Thread(std::string threadname, func_t<T> func, T& data): _threadname(threadname), _pid(0), _func(func), _isrunning(false), _data(data){}

3.Start函数和Join函数

 bool Start(){int n = pthread_create(&_pid, nullptr, ThreadRoutine, this);if (n == 0){_isrunning = true;return true;}return false;}bool Join(){if(!_isrunning) return true;int n=pthread_join(_pid,nullptr);if(n==0){_isrunning=false;return true;}else{return false;}}

4.在创建线程传递一个ThreadRoution函数

static void *ThreadRoutine(void *args) // 类内方法,{// (void)args; // 仅仅是为了防止编译器有告警Thread *ts = static_cast<Thread *>(args);ts->_func(ts->_data);return nullptr;}

ThreadRountion可不可以为类内函数?

不可以,类内函数默认隐藏的传递this指针,我们必须设置为静态函数函数,再传递this指针。

#pragma once#include <iostream>
#include <pthread.h>
#include <functional>
#include <cstring>template <class T>
using func_t = std::function<void(T&)>;template <class T>
class Thread
{
public:Thread(std::string threadname, func_t<T> func, T& data): _threadname(threadname), _pid(0), _func(func), _isrunning(false), _data(data){}static void *ThreadRoutine(void *args) // 类内方法,{// (void)args; // 仅仅是为了防止编译器有告警Thread *ts = static_cast<Thread *>(args);ts->_func(ts->_data);return nullptr;}bool Start(){int n = pthread_create(&_pid, nullptr, ThreadRoutine, this);if (n == 0){_isrunning = true;return true;}return false;}bool Join(){if(!_isrunning) return true;int n=pthread_join(_pid,nullptr);if(n==0){_isrunning=false;return true;}else{return false;}}const std::string& Threadname(){return _threadname;} private:std::string _threadname;pthread_t _pid;func_t<T> _func;bool _isrunning;T _data;
};

创建线程池

我们打算用queue来储存任务,用vector数组储存线程

当任务队列为空时,我们用条件变量去控制线程睡眠,队列Push进任务再控制线程醒来。

1.成员变量

private:queue<T> _taskq;vector<Thread<ThreadData>> _ptdv;pthread_mutex_t _mutex;pthread_cond_t _cond;int _thread_num;

2.构造函数

初始化锁,条件变量,并创建线程。

  pthread_pool(int thread_num = defaultthreadnum) : _thread_num(thread_num){pthread_mutex_init(&_mutex, nullptr);pthread_cond_init(&_cond, nullptr);for (int i = 1; i <= defaultthreadnum; i++){string threadname("thread-");threadname += to_string(i);ThreadData td(threadname);Thread<ThreadData> t(threadname,std::bind(&pthread_pool<T>::pthread_Run, this, std::placeholders::_1), td);_ptdv.push_back(t);lg.LogMessage(Info, "%s is created...\n", threadname.c_str());}}

任务队列为空,让所有线程休眠,队列中有任务,直接让线程执行任务:t()

void pthread_Run(ThreadData &data){while (true){T t;{LockGuard ld(&_mutex);if (_taskq.empty()){allthreadsleep(data);}t = _taskq.front();_taskq.pop();}t();{LockGuard ld(&_mutex);lg.LogMessage(Info, "Thread name:%s is handling: %s \n", data._name.c_str(), t.PrintTask().c_str());lg.LogMessage(Info, "Thread name:%s get result: %s \n", data._name.c_str(), t.PrintResult().c_str());}}}

3.进程唤醒与进程休眠

void allthreadwakeup(){pthread_cond_signal(&_cond);}
void allthreadsleep(const ThreadData &data){lg.LogMessage(Debug, "no task, %s is sleeping...\n", data._name.c_str());pthread_cond_wait(&_cond, &_mutex);}

4.Push()

    void Push(T &task){{LockGuard ld(&_mutex);_taskq.push(task);// 插入任务后唤醒进程allthreadwakeup();}}
#pragma once
#include <iostream>
#include <vector>
#include <queue>
#include <pthread.h>
#include <cstring>
#include <functional>
#include <unistd.h>
#include "pthread.hpp"
#include "LockGuard.hpp"
#include "Log.hpp"
using namespace std;
static const int defaultthreadnum = 5;template <class T>
using func_r = std::function<void(T)>;class ThreadData
{
public:ThreadData(string name) : _name(name){}~ThreadData(){}public:string _name;
};
template <class T>
class pthread_pool
{
public:static pthread_pool<T> *Getinstance(){if (instance == nullptr){pthread_mutex_lock(&_sig_ins);if (instance == nullptr){instance = new pthread_pool<T>(defaultthreadnum);lg.LogMessage(Info, "instance is create succeess...\n");return instance;}}}pthread_pool(int thread_num = defaultthreadnum) : _thread_num(thread_num){pthread_mutex_init(&_mutex, nullptr);pthread_cond_init(&_cond, nullptr);for (int i = 1; i <= defaultthreadnum; i++){string threadname("thread-");threadname += to_string(i);ThreadData td(threadname);Thread<ThreadData> t(threadname,std::bind(&pthread_pool<T>::pthread_Run, this, std::placeholders::_1), td);_ptdv.push_back(t);lg.LogMessage(Info, "%s is created...\n", threadname.c_str());}}pthread_pool(const pthread_pool<T> &pp) = delete;const pthread_pool<T> &operator=(const pthread_pool<T> &pp) = delete;void allthreadwakeup(){pthread_cond_signal(&_cond);}void allthreadsleep(const ThreadData &data){lg.LogMessage(Debug, "no task, %s is sleeping...\n", data._name.c_str());pthread_cond_wait(&_cond, &_mutex);}void pthread_Run(ThreadData &data){while (true){T t;{LockGuard ld(&_mutex);if (_taskq.empty()){allthreadsleep(data);}t = _taskq.front();_taskq.pop();}t();{LockGuard ld(&_mutex);lg.LogMessage(Info, "Thread name:%s is handling: %s \n", data._name.c_str(), t.PrintTask().c_str());lg.LogMessage(Info, "Thread name:%s get result: %s \n", data._name.c_str(), t.PrintResult().c_str());}}}void Start(){for (auto &th : _ptdv){th.Start();lg.LogMessage(Info, "%s is running ...\n", th.Threadname().c_str());}}void Push(T &task){{LockGuard ld(&_mutex);_taskq.push(task);// 插入任务后唤醒进程allthreadwakeup();}}// Just for debug success!void Wait(){for (auto &th : _ptdv){th.Join();}}~pthread_pool(){pthread_mutex_destroy(&_mutex);pthread_cond_destroy(&_cond);}private:queue<T> _taskq;vector<Thread<ThreadData>> _ptdv;pthread_mutex_t _mutex;pthread_cond_t _cond;int _thread_num;static pthread_pool *instance;static pthread_mutex_t _sig_ins;
};
template <class T>
pthread_pool<T> *pthread_pool<T>::instance = nullptr;
template <class T>
pthread_mutex_t pthread_pool<T>::_sig_ins = PTHREAD_MUTEX_INITIALIZER;

线程池单利化问题

  static pthread_pool<T> *Getinstance(){if (instance == nullptr){pthread_mutex_lock(&_sig_ins);if (instance == nullptr){instance = new pthread_pool<T>(defaultthreadnum);lg.LogMessage(Info, "instance is create succeess...\n");return instance;}}}

在获取单例的函数中,我们是需要加锁的,防止多个线程同时进入创建出多个单利。

相关文章:

创建线程池和封装锁

封装一个锁 1.封装一个Mutex class Mutex{public:Mutex(pthread_mutex_t * lock):_lock(lock){}void Lock(){pthread_mutex_lock(_lock);}void unLock(){pthread_mutex_unlock(_lock);}~Mutex(){}private:pthread_mutex_t *_lock; };2.封装一个LockGuard class LockGuard{pub…...

易图讯军用VR三维电子沙盘系统

深圳易图讯军用VR三维电子沙盘系统是一种集成了虚拟现实&#xff08;VR&#xff09;技术、三维建模技术、大数据分析、实时动态更新以及高度安全可靠的综合性军事指挥平台。该系统通过高精度三维模型真实再现战场环境&#xff0c;为指挥员提供沉浸式体验和交互操作的可能性&…...

LeetCode讲解篇之70. 爬楼梯

文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 爬楼梯有一个规律&#xff0c;爬到第n层楼梯的方法种数 爬到第n - 1层楼梯的方法种数 爬到第n - 1层楼梯的方法种数 也就是我们爬到第n层楼梯其实是从第n - 1层楼梯向上爬1层或者是n - 2层楼梯向上爬2层转换来…...

论文写作不再难,论文初稿快速成型法!

撰写论文是每个学者的必修课&#xff0c;我非常明白撰写论文的不易。撰写过程中会遇到各种困扰&#xff0c;如思路不清晰、论证不充分、语言表达不准确等。在这里以我的经验分享给大家一个能快速完成论文初稿的秘诀“AI导师写作”&#xff0c;希望能帮助还在为论文发愁的你。 …...

linux系统,监控进程运行状态并自动重启崩溃后的进程的多种方法

系统进程运行异常崩溃后&#xff0c;自动重启的方法 有的公司&#xff0c;会写monitor守护进程&#xff0c;监视各个进程的运行状态&#xff0c;异常时&#xff0c;自动重启&#xff0c;但是这种&#xff0c;通过一个进程 监护一个进程的做法&#xff0c;不太完美&#xff0c;…...

【JavaEE初阶】深入理解不同锁的意义,synchronized的加锁过程理解以及CAS的原子性实现(面试经典题);

前言 &#x1f31f;&#x1f31f;本期讲解关于锁的相关知识了解&#xff0c;这里涉及到高频面试题哦~~~ &#x1f308;上期博客在这里&#xff1a;【JavaEE初阶】深入理解线程池的概念以及Java标准库提供的方法参数分析-CSDN博客 &#x1f308;感兴趣的小伙伴看一看小编主页&am…...

详解Redis分布式锁在SpringBoot的@Async方法中没锁住的坑

背景 Redis分布式锁很有用处&#xff0c;在秒杀、抢购、订单、限流特别是一些用到异步分布式并行处理任务时频繁的用到&#xff0c;可以说它是一个BS架构的应用中最高频使用的技术之一。 但是我们经常会碰到这样的一个问题&#xff0c;那就是我们都按照标准做了但有时运行着、…...

怎么做接口自动化测试

在分层测试的“金字塔”模型中&#xff0c;接口测试属于第二层服务集成测试范畴。相比UI层&#xff08;主要是WEB或APP&#xff09;自动化测试而言&#xff0c;接口自动化测试收益更大&#xff0c;且容易实现&#xff0c;维护成本低&#xff0c;有着更高的投入产出比&#xff0…...

网络编程(18)——使用asio协程实现并发服务器

十八、day18 到目前为止&#xff0c;我们以及学习了单线程同步/异步服务器、多线程IOServicePool和多线程IOThreadPool模型&#xff0c;今天学习如何通过asio协程实现并发服务器。 并发服务器有以下几种好处&#xff1a; 协程比线程更轻量&#xff0c;创建和销毁协程的开销较…...

Koa2项目实战2(路由管理、项目结构优化)

添加路由&#xff08;处理不同的URL请求&#xff09; 路由&#xff1a;根据不同的URL&#xff0c;调用对应的处理函数。 每一个接口服务&#xff0c;最核心的功能是&#xff1a;根据不同的URL请求&#xff0c;返回不同的数据。也就是调用不同的接口返回不同的数据。 在 Node…...

决战Linux操作系统

前言&#xff1a; 你是否也曾经为Linux所困扰过&#xff0c;在网上找的资料零零散散&#xff0c;是否学完Linux后还是懵懵懂懂&#xff0c;别怕&#xff0c;这篇博客是博主精心为你准备的&#xff0c;现在&#xff0c;就让我们一起来走进Linux的世界&#xff0c;决战Linux&…...

OceanBase 3.2.2 数据库问题处理记录

只记录OceanBase 数据库与OCP的异常处理&#xff0c;其它组件暂时不写录。 一、问题1&#xff1a; 说明&#xff1a;OMS 出现异常&#xff0c;无法访问(OB无法访问) OB数据库架构&#xff1a;1:1:1 原因&#xff1a;某一台OBserver因为内存问题&#xff0c;被服务器直接kill掉…...

HCIP--以太网交换安全(二)端口安全

端口安全 一、端口安全概述 1.1、端口安全概述&#xff1a;端口安全是一种网络设备防护措施&#xff0c;通过将接口学习的MAC地址设为安全地址防止非法用户通信。 1.2、端口安全原理&#xff1a; 类型 定义 特点 安全动态MAC地址 使能端口而未是能Stichy MAC功能是转换的…...

在 Windows 11 安卓子系统中安装 APK 的操作指南

这个软件好像不可以在纯android系统中使用&#xff08;不知道是缺了什么&#xff09;&#xff0c;其他对于android的虚拟机要不缺少必要功能组件&#xff0c;要不性能过于低下。本方法致力于在带有谷歌框架WSA中运行该APK 在 Windows 11 安卓子系统中安装 APK 的操作指南 本指…...

[C语言] 函数详解:库函数与自定义函数

文章目录 函数的概念库函数和自定义函数库函数使用库函数示例常用库函数及头文件 自定义函数自定义函数的基本结构示例&#xff1a;实现两个数的求和函数自定义函数的好处 函数的返回值有返回值的函数无返回值的函数 函数的声明与调用声明函数在另一个文件中调用函数示例&#…...

0x11 科迈 RAS系统 Cookie验证越权漏洞

参考: 科迈 RAS系统 Cookie验证越权漏洞 | PeiQi文库 (wgpsec.org)免责声明 欢迎访问我的博客。以下内容仅供教育和信息用途: 合法性:我不支持或鼓励非法活动。请确保遵守法律法规。信息准确性:尽管我尽力提供准确的信息,但不保证其完全准确或适用。使用前请自行验证。风…...

MoonBit 双周报 Vol.57:AI助手功能增强、表达式优先级调整、JS 交互优化、标准库与实验库API多项更新!

2024-10-08 IDE更新 AI Codelens支持 /generate 和 /fix 命令 /generate 命令能够提供一个通用的用以生成代码的聊天界面。 /fix 命令能够读取当前函数的错误信息给出修复建议。 MoonBit更新 调整中缀表达式和if、match、loop、while、for、try表达式的优先级, 后者这些控制…...

element ui input textarea控制显示高度

样式代码 .testPage { position: absolute; left: 0; top: 0; right: 0; bottom: 0; display: flex; height: 100%; /* 控制输入框高度 */ .el-textarea { height: 90%; ::v-deep .el-textarea__inner { height: 90%; } } }...

Chromium 中chrome.downloads扩展接口c++

一、前端chrome.downloads 使用 chrome.downloads API 以编程方式启动、监控、操作和搜索下载内容。 权限 downloads 您必须在扩展程序清单中声明 "downloads" 权限&#xff0c;才能使用此 API。 {"name": "My extension",..."permiss…...

微信小程序常见问题

一、编译报错 [ app.json 文件内容错误] app.json: 在项目根目录未找到 app.json 解决办法&#xff1a; 微信开发者工具中打开设置->安全设置->打开服务端口用HBuilder X打开小程序文件夹&#xff0c;点击“运行到小程序模拟器”&#xff0c;生成配置文件&#xff0c;…...

Linux 新手必会 30 个高频基础命令(零基础可直接上手)

前言对于Linux新手来说&#xff0c;无需死记硬背所有命令&#xff0c;重点掌握这30个高频基础命令&#xff0c;就能完成日常90%的操作&#xff08;目录切换、文件管理、系统查看等&#xff09;。本文按“使用场景分类”&#xff0c;每个命令标注【用法示例新手提示】&#xff0…...

2026年支持人民币计价的金价追踪APP有哪些

家人们谁懂啊&#xff01;上周我发小蹲了3个月的50克古法金镯子终于下手&#xff0c;结账的时候才傻了眼&#xff1a;她之前用来盯金价的APP默认是美元离岸价&#xff0c;自己换算的时候忘了算汇率差和国内基础金价的浮动&#xff0c;预估的总价和实际付款差了快1800&#xff0…...

Keil MDK中EVR选项缺失的解决方案与原理

1. 问题现象解析&#xff1a;EVR选项缺失的典型表现 在Keil MDK开发环境中使用Event Recorder&#xff08;事件记录器&#xff09;时&#xff0c;开发者常会遇到一个令人困惑的现象&#xff1a;按照官方文档配置printf重定向到EVR时&#xff0c;STDOUT的下拉菜单中本该出现的&q…...

明日方舟自动化助手MAA:3步解放双手,让游戏回归乐趣

明日方舟自动化助手MAA&#xff1a;3步解放双手&#xff0c;让游戏回归乐趣 【免费下载链接】MaaAssistantArknights 《明日方舟》小助手&#xff0c;全日常一键长草&#xff01;| A one-click tool for the daily tasks of Arknights, supporting all clients. 项目地址: ht…...

Perplexity课程查询功能全链路拆解(从API底层到UI交互逻辑)

更多请点击&#xff1a; https://kaifayun.com 第一章&#xff1a;Perplexity课程查询功能全链路概览 Perplexity 的课程查询功能并非单一接口调用&#xff0c;而是一套覆盖用户意图理解、多源数据协同检索、结构化结果生成与实时反馈优化的端到端系统。其核心目标是将自然语言…...

Vue3生态系统:打造完整的前端开发体系

Vue3生态系统&#xff1a;打造完整的前端开发体系 前言 大家好&#xff0c;我是前端老炮儿。今天咱们来聊聊Vue3的生态系统。 如果说Vue3是一辆超级跑车&#xff0c;那它的生态系统就是配套的加油站、维修站和改装厂。一个好的框架不仅要有强大的核心能力&#xff0c;还要有…...

水培种菜翻车了?可能是水质问题!用NodeMCU和TDS传感器给你的营养液做个“体检”

水培种菜翻车了&#xff1f;可能是水质问题&#xff01;用NodeMCU和TDS传感器给你的营养液做个“体检” 看着阳台上蔫头耷脑的生菜叶子&#xff0c;你开始怀疑人生——明明按照教程配了营养液&#xff0c;定时补光通风&#xff0c;为什么植物就是长不好&#xff1f;别急着怪自己…...

别再傻傻重启了!用JRebel给IDEA装上‘秒级热更新’,Spring Boot开发效率翻倍

告别低效重启&#xff1a;用JRebel解锁Spring Boot开发的终极热更新体验 每次修改几行代码就要等待漫长的应用重启&#xff1f;Spring Boot DevTools的热加载功能已经无法满足你对开发效率的极致追求&#xff1f;作为长期奋战在Java开发一线的工程师&#xff0c;我深知这种重复…...

终极指南:如何快速免费解决GBK到UTF-8编码转换难题

终极指南&#xff1a;如何快速免费解决GBK到UTF-8编码转换难题 【免费下载链接】GBKtoUTF-8 To transcode text files from GBK to UTF-8 项目地址: https://gitcode.com/gh_mirrors/gb/GBKtoUTF-8 还在为乱码文件而烦恼吗&#xff1f;GBKtoUTF-8是一款专为中文文本编码…...

STM32 HAL库实战:用CD74HC4067扩展模拟输入通道,附完整工程代码

STM32 HAL库实战&#xff1a;用CD74HC4067扩展模拟输入通道&#xff0c;附完整工程代码 在嵌入式开发中&#xff0c;模拟信号采集是常见需求&#xff0c;但MCU内置ADC通道数量往往有限。当面对多路传感器信号采集时&#xff0c;如何经济高效地扩展输入通道成为开发者必须解决的…...