一步一步写线程之十一线程池应用内存池

news/2024/9/24 6:59:34/

一、内存池

内存池,非常好理解,就是存储内存的一个池子(Pool),一般来说,都是使用各种容器或者自己实现的类似容器的内存管理类。内存池其实就是为了解决两个主要问题,一个是内存反复分配回收的性能问题;另外一个就是小内存的反复分配导致的内存碎片问题。一般来说,内存池的管理以固定大小为宜(不固定也无所谓,但普适性可能就很差)。
使用内存池是有一些前提要求的,第一是要内存需要反复不断分配(高频);第二,内存分配大小存在一定的特征(比如大小有一个可控的限制);第三,内存分配要尽量快;第四,内存不可共用;第五,内存分配成功率高。
内存池的缺点也显而易见,第一就是增加了开发的复杂性;第二,浪费内存资源(这就看设计得的取舍);第三,简单内存应用不能使用;第四,无法处理大内存(特别是上百兆以后),这也是开源框架中,一般大内存都直接使用原始接口。
说明:对象池本质也是内存的管理,所以此处把二者简单的混为一谈。

二、内存池在线程池中的应用

在线程中,对内存的分配的要求,几乎都占全了。所以在一些大的涉及到内存管理的线程池中,一般都会有一个内存池作为辅助来处理数据的内存分配和管理。最典型的例子仍然是Web服务端,一个HTTP请求过来,都会有一个数据包,这个数据包的解析就需要内存分析回收,为了快捷和防止内存碎片一般会使用一个内存池来进行管理。而Web服务端一般是多线程(多进程)的,但用不用线程(进程)池,就不敢一概而论了。
而且,既然用到了线程池,说明程序还是比较复杂的,所以再增加内存池的复杂性,也算不得什么,投入和收益一般来说是合适的。不过在线程池中使用内存池,缺点就是要处理数据的同步(无锁编程以后再分析)。这种并发处理的方法有很多,可以分段串行(包括使用线程本地内存等),可以偷窃也可以使用互斥等等。

三、源码

下面看一个内存池应用在线程池中的例子:

#ifndef __MEMPOOLS_H__
#define __MEMPOOLS_H__#include <memory>
#include <queue>
#include <vector>template <typename T> class MemPools : public NoCopy {
public:MemPools() = default;~MemPools() = default;public:T Get() {std::lock_guard lg(this->mt_);T t = this->vec_.back();this->vec_.pop_back();this->count_--;return t;}void Set(T t) {std::lock_guard lg(this->mt_);this->vec_.emplace_back(t);this->count_++;}std::shared_ptr<T> GetPtr() {std::lock_guard lg(this->mt_);auto pt = this->pvec_.back();this->pvec_.pop_back();this->count_--;return pt;}void SetPtr(std::shared_ptr<T> pt) {std::lock_guard lg(this->mt_);this->pvec_.emplace_back(pt);this->count_++;}size_t GetMemPoolsLen() const { return this->count_; }void Clear() { this->vec_.clear(); }bool Extend(int count = 100, int flag = 0) { return this->createMemPools(count, flag); }private:bool initMemPools(int count = 1000, int flag = 0) {bool ret = true;ret = this->createMemPools(count, 0);return ret;}bool createMemPools(const int count, int flag) {bool ret = true;for (int num = 0; num < count; num++) {if (0 == flag) {T t;std::lock_guard lg(this->mt_);this->vec_.emplace_back(t);} else if (1 == flag) {std::shared_ptr<T> pt = std::make_shared<T>();std::lock_guard lg(this->mt_);this->pvec_.emplace_back(pt);}}this->count_ += count;return ret;}private:std::vector<T> vec_;std::vector<std::shared_ptr<T>> pvec_;size_t count_ = 0;std::mutex mt_;
};#endif // __MEMPOOLS_H__

是不是发现内存池和任务管理的模板类有些相似?确实。但二者其实有着本质的不同。前者需要动态适应不同的容器并且一般不会自己主动分配内存对象,而内存池一般只需要有一种内存管理容器即可,同时必须提前创建一系列的相关内存对象(所以有的也叫对象池)。代码的应用也很简单,直接将原来的分配回收内存的地方改成这里的Get和Set相关即可。上面的代码有一点小瑕疵,直接返回了对象,其实返回对象的引用或者直接使用指针其实是最好的。
掌握方法,踏入门槛,这是学习的最基本的形式。这就和打仗一样,集中优势兵力,突破一点,然后再全线展开。

四、总结

可能有的同学说这个和在网上或者书上看到的内存池不大一样啊?其实本质是一样的。直接分配内存控制比特流,然后再分块拆分和上面的直接进行对象分配本质是相同的,不同的在于可能直接使用比特流会更灵活。或者说把本文叫做对象池,可能就更容易理解了。
这一篇只是针对线程池中的内存池应用进行一个基础的分析说明,后面会抽时间对内存池有一个全面的分析说明。诸如内存池的大小分组(微型、小型、中型、大型)和是否连续处置(内存一次分配,分块使用)等,本文都没有涉及,目的只是一个很简单的在线程池中使用内存池,知其所以然即可。细节需要自己不断的深入研究和学习,掌握后按照这样的接口使用即可。
学以致用,才是根本。


http://www.ppmy.cn/news/1450849.html

相关文章

电力能源箱3D可视化:开启智慧能源管理新篇章

随着科技的不断进步&#xff0c;电力能源箱的管理与维护逐渐向着智能化、可视化的方向发展。3D可视化技术的崛起&#xff0c;不仅极大地提升了能源管理的效率&#xff0c;更以其直观、生动的特点&#xff0c;引领着电力能源管理领域迈入了一个全新的时代。 电力能源箱作为电力系…

【分享】如何将word格式文档转化为PDF格式

在日常的办公和学习中&#xff0c;我们经常需要将Word文档转换为PDF格式。PDF作为一种通用的文件格式&#xff0c;具有跨平台、易读性高等优点&#xff0c;因此在许多场合下都更为适用。那么&#xff0c;如何实现Word转PDF呢&#xff1f;本文将介绍几种常用的方法&#xff0c;帮…

观察者模式实战:解密最热门的设计模式之一

文章目录 前言一、什么是观察者模式二、Java实现观察者模式2.1 观察者接口2.2 具体观察者2.3 基础发布者2.4 具体发布者2.5 消息发送 三、Spring实现观察者模式3.1 定义事件类3.2 具体观察者3.3 具体发布者3.4 消息发送 总结 前言 随着系统的复杂度变高&#xff0c;我们就会采…

Java中的流(Stream)以及它们在集合操作中的作用和例子

Java中的流&#xff08;Stream&#xff09;是Java 8引入的一个新特性&#xff0c;主要用于处理集合数据。流提供了一种声明式的方式来处理数据&#xff0c;使代码更加简洁和易于理解。通过使用流&#xff0c;你可以对集合数据进行各种复杂的操作&#xff0c;如过滤、映射、排序…

RocketMq详解:一、RocketMQ 介绍及基本概念

文章目录 前言1.RocketMQ简介2.RocketMQ 特点3.核心特性4.应用场景5.RocketMQ 优势6.RocketMQ 四大核心组件6.1 NameServer1.NameServer作用2.NameServer被设计为无状态的原因3.和NameServer和Zookeeper的区别4.NameServer的高可用保障 6.2 Broker1.Broker部署方式2.高可用与负…

[华为OD] C卷 服务器cpu交换 现有两组服务器QA和B,每组有多个算力不同的CPU 100

题目&#xff1a; 现有两组服务器QA和B,每组有多个算力不同的CPU,其中A[i]是A组第i个CPU的运算能 力&#xff0c;B[i]是B组第i个CPU的运算能力。一组服务器的总算力是各CPU的算力之和。 为了让两组服务器的算力相等&#xff0c;允许从每组各选出一个CPU进行一次交换。 求两…

蓝桥杯练习系统(算法训练)ALGO-950 逆序数奇偶

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 老虎moreD是一个勤于思考的青年&#xff0c;线性代数行列式时&#xff0c;其定义中提到了逆序数这一概念。不过众所周知我们…

3D看车有哪些强大的功能?适合哪些企业使用?

3D看车是一种创新的汽车展示方式&#xff0c;它提供了许多强大的功能&#xff0c;特别适合汽车行业的企业使用。 3D看车可实现哪些功能&#xff1f; 1、细节展示&#xff1a; 51建模网提供全套汽车行业3D数字化解决方案&#xff0c;3D看车能够将汽车展示得更加栩栩如生&…