1. 设计思路
- 内存块划分:将大块内存划分成固定大小的小块,以减少内存碎片。
- 空闲链表:使用链表来管理空闲的内存块,方便快速分配和回收。
- 线程安全:使用互斥锁(
std::mutex
)来保证多线程环境下内存池操作的线程安全。
2. 代码实现
#include <iostream>
#include <vector>
#include <mutex>
class MemoryPool {
private:
const size_t blockSize;
const size_t poolSize;
std::vector<char*> blocks;
char* pool;
std::mutex mtx;
struct FreeListNode {
FreeListNode* next;
};
FreeListNode* freeList;
public:
MemoryPool(size_t blockSize, size_t numBlocks)
: blockSize(blockSize), poolSize(numBlocks * blockSize), freeList(nullptr) {
pool = new char[poolSize];
for (size_t i = 0; i < numBlocks; ++i) {
char* block = pool + i * blockSize;
blocks.push_back(block);
FreeListNode* node = reinterpret_cast<FreeListNode*>(block);
node->next = freeList;
freeList = node;
}
}
~MemoryPool() {
delete[] pool;
}
void* allocate() {
std::lock_guard<std::mutex> lock(mtx);
if (freeList == nullptr) {
return nullptr;
}
FreeListNode* node = freeList;
freeList = freeList->next;
return node;
}
void deallocate(void* ptr) {
std::lock_guard<std::mutex> lock(mtx);
FreeListNode* node = reinterpret_cast<FreeListNode*>(ptr);
node->next = freeList;
freeList = node;
}
};
3. 内存碎片问题处理
- 固定大小块:通过分配固定大小的内存块,减少因不同大小内存请求导致的外部碎片。
- 合并空闲块:对于相邻的空闲块,可以在释放时进行合并,减少内部碎片。
4. 线程安全问题处理
- 互斥锁:使用
std::mutex
来保护对空闲链表的操作,确保在多线程环境下内存池操作的原子性。
5. 不同应用场景下的优化
- 高并发读场景:可以考虑使用读写锁(
std::shared_mutex
),允许多个线程同时进行读操作,提高并发性能。
- 不同大小内存请求:可以设计多个不同大小块的内存池,根据请求大小选择合适的内存池进行分配。
- 长时间运行应用:定期进行内存碎片整理,例如在空闲时段合并空闲块,以维持高效的内存分配。