IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 项目--高并发内存池 -> 正文阅读

[Java知识库]项目--高并发内存池

学习C++也有不少时日了,今天我们来学习一个项目,该项目是借鉴谷歌的tc-malloc,让我们一起来认识一下这个设计极其优秀的项目吧

需求分析

我们该项目利用了设计模式中的池化技术,在传统的内存池上进行了优化,该内存池可以有效地提高内存申请效率以及解决内存碎片化的问题

普通内存池的优缺点

我们先来回顾一下内存池的主要思路,就是预先开辟一大块内存,当我们程序需要使用内存时,直接从该大块内存中拿取一块,可以提高申请释放效率,而不需要再去new/malloc从堆中申请内存

优点:提高效率,解决部分内存碎片问题

缺点:无法处理高并发时申请内存存在的锁竞争问题,该问题会使效率降低

我们的内存池解决的问题就是上面这些问题

主要设计思路

高并发内存池整体框架由以下三部分组成,各部分的功能如下:

线程缓存(thread cache):每个线程独有线程缓存,主要解决多线程下高并发运行场景线程之间的锁竞争问题。线程缓存模块可以为线程提供小于64k内存的分配,并且多个线程并发运行不需要加锁。
中心控制缓存(central control cache):中心控制缓存顾名思义,是高并发内存池的中心结构主要用来控制内存的调度问题。负责大块内存切割分配给线程缓存以及回收线程缓存中多余的内存进行合并归还给页缓存,达到内存分配在多个线程中更均衡的按需调度的目的,它在整个项目中起着承上启下的作用。(注意:这里需要加锁,当多个线程同时向中心控制缓存申请或归还内存时就存在线程安全问题,但是这种情况是极少发生的,并不会对程序的效率产生较大的影响,总体来说利大于弊)
页缓存(page cache):以页为单位申请内存,为中心控制缓存提供大块内存。当中心控制缓存中没有内存对象时,可以从page cache中以页为单位按需获取大块内存,同时page cache还会回收central control cache的内存进行合并缓解内存碎片问题。

那么我们就从0开始对这个项目进行实现吧

thread cache线程缓存

首先,我们思考一下,我们的这个内存池最主要的目的是什么?就是可以同时分配内存给不同的线程,基于这一点,参考我们内存池的设计,我们设计了一个成员是自由双向链表的哈希桶作为thread_cache的主要结构

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bmzICDnlJ8=,size_20,color_FFFFFF,t_70,g_se,x_16?

private:FreeList _freeLists[NFREELISTS];//自由链表大小为NFREELISTS

那么我们就需要对双向链表进行基础实现

FreeList类

我们既然是挂在哈希桶上,要用这个链表来对内存块进行存储,所以我们结点需要1.头结点指针。2.哈希桶下结点个数。

private:void* _head = nullptr;size_t _size = 0;

我们想到,当我们一个线程需要内存时,我们将对应大小的内存返回给线程,所以我们诞生了

// 头删void* Pop()//将一份内存返回给线程{void* obj = _head;_head = NextObj(_head);_size -= 1;return obj;}

我们在这里需要对NextObj(_head)进行说明,这个函数其实是代替链表的next而生的,下面是他的具体实现

inline void*& NextObj(void* obj)//obj的下一个结点{return *((void**)obj);//我们将obj的前4/8个字节用以存储下一个节点的地址,返回obj的前4/8个字节//相当于返回了下一个结点,这里我们采用对void**解引用,就是因为使用void**才真正提取出了一块内存对//象随着32位/64位机器的不同取出前4/8个字节(解void**就是看void*的大小,而void*的大小在32位下就是4,64位就是8),注:void*一般而言是不能解引用的(Linux下可以),但是void**可以}

有了将内存传给线程,那么就会有线程将用完的内存还给内存池,随意我们的链表还有插入操作

// 头插void Push(void* obj){NextObj(obj) = _head;_head = obj;_size += 1;}

以及一些基本的函数

bool Empty(){return _head == nullptr;}size_t MaxSize(){return _max_size;}void SetMaxSize(size_t n){_max_size = n;}size_t Size(){return _size;}

?

?

?

?

?

?

?

?


?

?

?

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-02-14 20:59:25  更:2022-02-14 21:00:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 12:50:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码