C++实现高并发内存池

1 篇文章 1 订阅

关于高并发内存池的项目的博客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中的哈希桶清空(不清空也没事)。
在这里插入图片描述

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

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今天也要写bug、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值