前面两篇博客主要介绍了内存池的原理和实现,这篇博客主要是介绍如何优化多线程安全的内存池
内存池的实现和管理(二)中内存池的实现代码存在的问题
虽然在内存申请和释放的时候,使用lock_guard()实现了多线程安全的内存池,但是频繁的加锁和解锁带来了不必要的上下文切换开销,导致整个内存池的使用性能下降许多(主要体现在单次申请释放/释放内存需要的时间上升),和直接向系统申请内存的效率差许多
也就是说,虽然可以减少内存碎片的产生,但是并不能提高申请内存的效率
优化方案一:
在多线程情况下,申请内存时加锁是必然的,每次申请向内存池申请内存块的时候都要即时加锁,但是释放内存块的时候我们可以延时释放,做一个定时任务去遍历内存池中管理内存块的链表,加锁一次释放多个内存块,这样就减少了释放内存块时的加锁次数
在内存池中释放内存块有两个步骤:
1、把内存使用标记从已使用状态改为未使用
2、第一个未使用内存块指针的移动
释放内存时只要求第2步需要互斥进行,所以我们在释放的时候先修改标记状态(不加锁),执行一次定时任务,遍历管理内存块的链表,修改第一个未分配内存块的指针(加锁)
优化方案二:
产生冲突的根本原因是因为多个线程共用一个内存池,我们可以让每个线程都拥有一个内存池,这样内存块的申请和释放都在本线程内进行,自然不用加锁
但是这样在多线程的 情况下使用不方便,内存利用率低下,并且管理内存池很繁琐
换一个思路,依然时多个线程共用一个内存池,但是我们给不同的线程安排不同的内存使用区域,这样即时不加锁也可以实现内存池的互斥使用
具体做法是可以给num个内存块进行编号,假设有n个线程,每个线程可使用的内存块个数t=num/n,根据线程id确定该线程使用的内存区域为[t*(id-1),t*id);id的取值范围为[1,n]
参考博客https://blog.csdn.net/luzubodfgs/article/details/65632609