多线程环境下内存池的实现(C++)

文章目录

  • [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;
}
相关推荐
Yang.991 小时前
基于Windows系统用C++做一个点名工具
c++·windows·sql·visual studio code·sqlite3
熬夜学编程的小王1 小时前
【初阶数据结构篇】双向链表的实现(赋源码)
数据结构·c++·链表·双向链表
zz40_2 小时前
C++自己写类 和 运算符重载函数
c++
六月的翅膀2 小时前
C++:实例访问静态成员函数和类访问静态成员函数有什么区别
开发语言·c++
liujjjiyun2 小时前
小R的随机播放顺序
数据结构·c++·算法
¥ 多多¥2 小时前
c++中mystring运算符重载
开发语言·c++·算法
天若有情6733 小时前
c++框架设计展示---提高开发效率!
java·c++·算法
Root_Smile4 小时前
【C++】类和对象
开发语言·c++
Reese_Cool4 小时前
【数据结构与算法】排序
java·c语言·开发语言·数据结构·c++·算法·排序算法