• C++实现高并发内存池


    关于高并发内存池的项目的博客CSDN上已经有很多,其中个人认为最优秀的是龙哥写的【项目设计】高并发内存池,强烈建议阅读。

    此篇博客会在龙哥博客基础上进行总结和拓展,包括如何进行修改能够兼容Windows和Linux两种操作系统、哪些地方的细节需要注意等等。

    项目源代码: C++实现的高并发内存池项目 。直接复制源代码即可在Windows或Linux中运行。


    实现Linux与Windows跨系统运行

    原来的项目主要是在Windows下运行,如果要兼容Linux,首先需要将Linux下申请和释放内存的接口补在条件编译那里:
    在这里插入图片描述

    另外由于Linux下并没有Windows自带的TLS接口,需要将TLS改成Linux下的__thread,在使用TLS时直接使用条件编译即可:
    在这里插入图片描述

    Linux下并不支持atomic的定义时就初始化,所以要先定义然后再赋值。
    在这里插入图片描述

    Linux与Windowsclock()函数的返回值为硬件滴答数,与编译器有关。

    在Windows的VS下每1000个滴答是一秒,在Linux的g++下为1000000个滴答为一秒。所以Linux下的返回值是Windows下的一千倍。

    如果想要计算多少秒,需要除以CLOCKS_PER_SEC,它用来表示一秒钟会有多少个时钟计时单元,也就是硬件滴答数。

    解决完上述问题只需要编写makefile即可运行程序:
    在这里插入图片描述

    在这里插入图片描述


    一些需要注意的问题

    定长内存池加锁以及大小的问题

    之前的定长内存池是没有锁的,所以在多线程使用定长内存池申请pTLSThreadCache时就会出现问题:在这里插入图片描述

    这里有两种解决办法,一种是龙哥那种在申请前加锁。
    在这里插入图片描述

    另一种则是在定长内存池内部加锁,在申请和释放内存时进行加锁和解锁:
    在这里插入图片描述

    这里更加推荐第二种,因为这样能够让定长内存池更加安全,减少外部加锁的繁琐操作。

    另外定长内存池有两个需要注意的地方,一个是obj的大小必须要比一个指针的空间大,否则无法形成链表;第二个是大块空间不够时,我们需要重新开辟一大块空间,但这新开辟的大块空间可能还是不够obj的大小(比如在64位时使用3层基数树那里需要开辟第一层节点时,就会出现这种情况,因为第一层节点需要开辟1M多的空间,但为了避免浪费,定长内存池我们不会一次性开那么大的大块内存),所以我们需要进行一次判断,如果obj的大小比大块空间还大的话,则需要开辟obj大小的空间。

    在这里插入图片描述

    线程结束存在内存泄漏的问题

    虽然我们已经有了ThreadCache将内存还给CentralCache的接口,但归还有一个前提,那就是ThreadCache哈希桶中链表的长度必须要到一定的长度才会归还。

    这也就意味着当一个线程结束,即使程序员已经调用了ConcurrentFree来归还内存,但归还只是还给ThreadCache,ThreadCache并不一定会还给CentralCache。

    所以ThreadCache中会存在内存泄漏的问题。

    这里的解决办法有很多,最简单的方式就是写一个接口手动归还ThreadCache中的内存,其本质就是对ReleaseListToSpans接口的复用,另外还需要将ThreadCache中的哈希桶清空(不清空也没事)。
    在这里插入图片描述

    当然手动调用毕竟不友好,会出现忘记调用的情况,这也是后续优化的点,让其随线程结束自动调用。

  • 相关阅读:
    CISP-PTE学习总结之基础练习题(三)
    图文看懂JavaScritpt引擎V8与JS执行过程
    揭示GPT Tokenizer的工作原理
    130道基础OJ编程题之: 39 ~ 46 道
    ucos2源码分析---内核部分(三)
    HackTheBox-Starting Point--Tier 2---Base
    基于PHP的连锁酒店管理系统
    手机银行APP评测系列:天津银行持续优化手机银行用户体验,但仍需加强细节提升
    工业无线网关在实际生产中的应用效果和价值-天拓四方
    [重庆思庄每日技术分享]-回收ORACLE数据文件所占用空间
  • 原文地址:https://blog.csdn.net/qq_52670477/article/details/125796117