文章目录
- [1. 无锁情况下内存池存在的问题](#1. 无锁情况下内存池存在的问题)
- [2. 基于互斥锁mutex实现](#2. 基于互斥锁mutex实现)
- [3. 基于原子变量atomic实现](#3. 基于原子变量atomic实现)
- [4. 每个线程维护自己的内存池](#4. 每个线程维护自己的内存池)
1. 无锁情况下内存池存在的问题
可能发生一块内存被多个线程获取的情况,导致这几个线程的数据出现错乱。
cpp
#include <iostream>
#include <vector>
#include <thread>
#include <cstdlib>
#include <cstring>
const size_t BLOCK_SIZE = 64; // 每个块的大小
const size_t POOL_SIZE = 1024; // 内存池块数
class MemoryPool {
public:
MemoryPool() {
pool = malloc(BLOCK_SIZE * POOL_SIZE);
memset(pool, 0, BLOCK_SIZE * POOL_SIZE);
for (size_t i = 0; i < POOL_SIZE; ++i) {
void* block = static_cast<char*>(pool) + i * BLOCK_SIZE;
freeList.push_back(block); // 初始化空闲链表
}
}
~MemoryPool() {
free(pool);
}
void* allocate() {
if (freeList.empty()) {
return nullptr; // 内存池已空
}
void* block = freeList.back();
freeList.pop_back();
return block;
}
void free(void* ptr) {
freeList.push_back(ptr); // 将内存块放回空闲链表
}
private:
void* pool; // 内存池
std::vector<void*> freeList; // 空闲链表
};
// 线程入口函数
void threadFunction(MemoryPool& memoryPool) {
while (true)
{
void* ptr = memoryPool.allocate();
if (ptr) {
std::cout << "Thread " << std::this_thread::get_id()
<< " allocated memory at: " << ptr << std::endl;
// 使用分配的内存
std::memset(ptr, 0, BLOCK_SIZE); // 示例:清空分配的内存
// 模拟业务处理时间
std::this_thread::sleep_for(std::chrono::milliseconds(200));
// 释放内存
memoryPool.free(ptr);
std::cout << "Thread " << std::this_thread::get_id()
<< " freed memory at: " << ptr << std::endl;
} else {
std::cout << "Thread " << std::this_thread::get_id()
<< " failed to allocate memory." << std::endl;
}
}
}
int main() {
MemoryPool memoryPool;
const int numThreads = 8;
std::vector<std::thread> threads;
for (int i = 0; i < numThreads; ++i) {
threads.emplace_back(threadFunction, std::ref(memoryPool));
}
for (auto& thread : threads) {
thread.join();
}
return 0;
}
内存块0x57ff7f529cf0
被线程0x7f8eade00640
获取后,还没释放,就被线程0x7f8eafc00640
再次获取。
由于线程入口函数threadFunction与主函数main(),在下面的代码中不再发生变化,因此将省略这两个部分,聚焦于线程池类MemoryPool的实现。
2. 基于互斥锁mutex实现
cpp
class MemoryPool {
public:
MemoryPool() {
pool = malloc(BLOCK_SIZE * POOL_SIZE);
memset(pool, 0, BLOCK_SIZE * POOL_SIZE);
for (size_t i = 0; i < POOL_SIZE; ++i) {
void* block = static_cast<char*>(pool) + i * BLOCK_SIZE;
freeList.push_back(block); // 初始化空闲链表
}
}
~MemoryPool() {
free(pool);
}
void* allocate() {
// 生命周期结束会自动释放锁,通过析构函数实现
std::lock_guard<std::mutex> lock(mutex);
if (freeList.empty()) {
return nullptr; // 内存池已空
}
void* block = freeList.back();
freeList.pop_back();
return block;
}
void free(void* ptr) {
// 生命周期结束会自动释放锁,通过析构函数实现
std::lock_guard<std::mutex> lock(mutex);
freeList.push_back(ptr); // 将内存块放回空闲链表
}
private:
void* pool; // 内存池
std::vector<void*> freeList; // 空闲链表
std::mutex mutex; // 互斥量
};
3. 基于原子变量atomic实现
cpp
class MemoryPool {
public:
MemoryPool() {
pool = malloc(BLOCK_SIZE * POOL_SIZE);
memset(pool, 0, BLOCK_SIZE * POOL_SIZE);
for (size_t i = 0; i < POOL_SIZE; ++i) {
freeList[i].store(static_cast<char*>(pool) + i * BLOCK_SIZE);
}
freeHead.store(0);
}
~MemoryPool() {
free(pool);
}
void* allocate() {
while (true){
size_t head = freeHead.load();
if (head >= POOL_SIZE) {
return nullptr; // 内存池已空
}
// 尝试获取下一个空闲块
void* block = freeList[head].load();
if (freeHead.compare_exchange_strong(head, head + 1)) {
// 成功获取
return block;
}
}
}
void free(void* ptr) {
while (true) {
size_t head = freeHead.load();
if (head == 0) {
// 如果已满,直接返回
return;
}
// 将块放回空闲链表
freeList[head - 1].store(ptr);
if (freeHead.compare_exchange_strong(head, head - 1)) {
return; // 成功释放
}
}
}
private:
void* pool; // 内存池
std::atomic<void*> freeList[POOL_SIZE]; // 空闲链表
std::atomic<size_t> freeHead; // 当前空闲块的索引
};
4. 每个线程维护自己的内存池
cpp
class MemoryPool {
public:
MemoryPool() {
pool = malloc(BLOCK_SIZE * POOL_SIZE);
memset(pool, 0, BLOCK_SIZE * POOL_SIZE);
for (size_t i = 0; i < POOL_SIZE; ++i) {
void* block = static_cast<char*>(pool) + i * BLOCK_SIZE;
freeList.push_back(block); // 初始化空闲链表
}
}
~MemoryPool() {
free(pool);
}
void* allocate() {
if (freeList.empty()) {
return nullptr; // 内存池已空
}
void* block = freeList.back();
freeList.pop_back();
return block;
}
void free(void* ptr) {
freeList.push_back(ptr); // 将内存块放回空闲链表
}
private:
void* pool; // 内存池
std::vector<void*> freeList; // 空闲链表
};
int main() {
const int numThreads = 16;
std::vector<std::thread> threads;
std::vector<MemoryPool> pools;
for (int i = 0; i < numThreads; ++i) {
pools.push_back(MemoryPool()); // 为每个线程创建自己的内存池
threads.emplace_back(threadFunction, std::ref(pools[i]));
}
for (auto& thread : threads) {
thread.join();
}
return 0;
}