当前位置: 首页 > news >正文

高并发内存池(4)-TLS:Thread Local Storage

高并发内存池(4)-TLS:Thread Local Storage

每个线程都有哈希桶,哈希桶里面有自由链表

进程里面也会有多个线程,怎么解决序号问题,如果同时来创建,也会遇到锁的问题,这时候要借助TLS

线程局部存储(TLS),是一种变量的存储方法,这个变量在它所在的线程内是全局可访问的,但是不能被其他线程访问到,这样就保持了数据的线程独立性。而熟知的全局变量,是所有线程都可以访问的,这样就不可避免需要锁来控制,增加了控制成本和代码复杂度。

目前使用TLS的方法有多种,POSIX的pthread.h提供了一组API来实现此功能

int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));
int pthread_key_delete(pthread_key_t key);
void *pthread_getspecific(pthread_key_t key);
int pthread_setspecific(pthread_key_t key, const void *value);

除了API的方式,GCC的编译器也支持语言级别的用法,这样比用API调用,更简单

__thread int i;
extern __thread struct state s;
static __thread char *p

使用GCC编译级别支持的方式来实现TLS

#include<iostream>
#include<pthread.h>
#include<unistd.h>using namespace std;
__thread int iVar = 100;void* Thread1(void *arg)
{iVar += 200;cout<<"Thead1 Val : "<<iVar<<endl;
}void* Thread2(void *arg)
{iVar += 400;sleep(1);cout<<"Thead2 Val : "<<iVar<<endl;
}int main()
{pthread_t pid1, pid2;pthread_create(&pid1, NULL, Thread1, NULL);pthread_create(&pid2, NULL, Thread2, NULL);pthread_join(pid1, NULL);pthread_join(pid2, NULL);return 0;
}

我们这样写:(采用静态库,动态还需要调用函数)

static _declspec(thread) ThreadCache* pTLSThreadCache = nullptr;

我们创建一个头文件去封装:

#pragma once#include "Common.h"
#include "ThreadCache.h"
#include "ObjectPool.h"//申请空间
static void* ConcurrentAlloc(size_t size)
{//如果大于最大的存储空间if (size > MAX_BYTES){//向上对齐取空间size_t alignSize = SizeClass::RoundUp(size);}// 通过TLS 每个线程无锁的获取自己的专属的ThreadCache对象else{pTLSThreadCache = new ThreadCache;}//返回所需要申请的空间return pTLSThreadCache->Allocate(size);
}//释放空间
static void ConCurrentFree(void* ptr)
{}

还要做测试:

#include "ConcurrentAlloc.h"void Alloc1()
{for (size_t i = 0; i < 5; ++i){void* ptr = ConcurrentAlloc(6);}
}void Alloc2()
{for (size_t i = 0; i < 5; ++i){void* ptr = ConcurrentAlloc(7);}
}void TLSTest()
{std::thread t1(Alloc1);//​​等待线程执行完成​​。t1.join();std::thread t2(Alloc2);//​​等待线程执行完成​​。t2.join();
}

还有释放内存的过程:

//释放内存
void ThreadCache::Deallocate(void* ptr, size_t size)
{//判断指针是否为空assert(ptr);//判断内存是否为空assert(size <= MAX_BYTES);// 找对映射的自由链表桶,对象插入进入size_t index = SizeClass::Index(size);_freeLists[index].Push(ptr);
}
http://www.dtcms.com/a/350381.html

相关文章:

  • Vue.nextTick讲解
  • kubectl 客户端访问 Kubernetes API Server 不通的原因排查与解决办法
  • 800G时代!全场景光模块矩阵解锁数据中心超高速未来
  • AR眼镜赋能矿业冶金数字化转型
  • Wireshark笔记-DHCP流程与数据包解析
  • Linux驱动开发笔记(七)——并发与竞争(上)——原子操作
  • SQLite 全面指南与常用操作
  • 没有AI背景的团队如何快速进行AI开发
  • expdp导出dmp到本地
  • docker 安装配置 redis
  • PDF处理控件Spire.PDF系列教程:在 C# 中实现 PDF 与字节数组的互转
  • 2025年06月 Python(二级)真题解析#中国电子学会#全国青少年软件编程等级考试
  • synchronized关键字的底层原理
  • 蘑兔音乐:创作好搭子
  • 嵌入式C语言进阶:深入理解sizeof操作符的精妙用法
  • 隧道监测实训模型
  • 讲解 JavaScript 中的深拷贝和浅拷贝
  • PyPI 是什么?
  • CCleaner中文版:强大的系统优化与隐私保护工具,支持清理磁盘、注册表和卸载软件
  • `mysql_query()` 数据库查询函数
  • Ubuntu 22.04 中安装 ROS2 Humble
  • Java AI插件“飞算“实战测试:一键生成医院药品管理系统
  • Maven下载历史版本
  • 大模型微调 Prompt Tuning与P-Tuning 的区别?
  • 【44页PPT】DeepSeek在银行业务场景的应用(附下载方式)
  • AI 应用开发:从 Prompt 工程到实战应用开发
  • 基于RD算法的多目标SAR成像原理及MATLAB实现
  • 离线开发平台-HTTP数据同步到Doris数仓能力演示
  • GNN:用MPNN(消息传递神经网络)落地最短路径问题模型训练全流程
  • VS2010 在查找预编译头使用时跳过