threadcache实现细节(二)
目录
- TLS(thread local storage)(解决锁的问题)
- Linux下的TLS
- Windows下的TLS
- 声明_declspec(thread)
- static void* ConcurrentAlloc(size_t size)申请线程对象
- void ThreadCache::Deallocate(void* ptr, size_t size)归还空间给thread cache
- static void ConcurrentFree(void* ptr, size_t size)归还线程对象
- 测试代码
- 创建多线程环境
- 创建线程
感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接
🐒🐒🐒 个人主页
🥸🥸🥸 C语言
🐿️🐿️🐿️ C语言例题
🐣🐣🐣 python
🐓🐓🐓 数据结构C语言
🐔🐔🐔 C++
🐿️🐿️🐿️ 文章链接目录
🤠🤠🤠 高并发内存池项目
TLS(thread local storage)(解决锁的问题)
在之前有说过高并发内存池中每个线程都有自己独享的thread cache,而thread cache在之前的文章中也说到过是哈希桶结构,现在的问题是我们如何让每个线程都独享自己的thread cache呢
在多线程中,在一个进程里可能有多个线程,多个线程共享进程地址的空间,每个线程有自己独立的空间 栈等等,每个线程也共享全局段 代码段等等
比如下图中有三个thread cache,我们怎么确定他对应的线程能够独享呢,或者说谁是谁的thread cache,什么时候创建thread cache呢,如果是哪个线程申请的时候再创建的话就会涉及到加锁的问题,因为可能两个线程同时申请
具体要解决锁问题就需要用TLS
一个线程修改的内存内容,对所有线程都生效。这是一个优点也是一个缺点。说它是优点,线程的数据交换变得非常快捷。说它是缺点,一个线程死掉了,其它线程也性命不保; 多个线程访问共享数据,需要昂贵的同步开销,也容易造成同步相关的BUG
如果需要在一个线程内部的各个函数调用都能访问、但其它线程不能访问的变量(被称为static memory local to a thread 线程局部静态变量),就需要新的机制来实现。这就是TLS
TLS的功能简单的来说就是这个线程里面的东西其他线程不可以访问
Linux下的TLS
Thread Local Storage(线程局部存储)TLS
Windows下的TLS
声明_declspec(thread)
static _declspec(thread)ThreadCache* pTLSThreadCache = nullptr
当我们声明后每个线程都有他自己的pTLSThreadCache h,这里用static修饰是为了避免在其他文件冲突
static void* ConcurrentAlloc(size_t size)申请线程对象
这里用static修饰是为了避免在多个文件时链接属性冲突问题
static void* ConcurrentAlloc(size_t size)
{
if (pTLSThreadCache == nullptr)
{
pTLSThreadCache = new ThreadCache;
}
cout << std::this_thread::get_id() << ":" << pTLSThreadCache << endl;
return pTLSThreadCache->Allocate(size);
}
void ThreadCache::Deallocate(void* ptr, size_t size)归还空间给thread cache
void ThreadCache::Deallocate(void* ptr, size_t size)
{
assert(ptr);
assert(size <= MAX_BYTES);
size_t index = SizeClass::Index(size);//计算桶的位置
_freeLists[index].Push(ptr);//插入桶
}
因为thread cache是哈希桶结构,在归还的时候要知道是在哪个桶,所以要用之前的已经写好的函数Index(size)计算桶的位置,然后再用_freeLists[index].Push(ptr),将空间偷插进自由链表中
static void ConcurrentFree(void* ptr, size_t size)归还线程对象
static void ConcurrentFree(void* ptr, size_t size)
{
assert(pTLSThreadCache);
pTLSThreadCache->Deallocate(ptr, size);
}
测试代码
因为要测试多线程的情况,所以要包含C++11的一个头文件thread用来创建多线程场景
创建多线程环境
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);
}
}
这里的ConcurrentAlloc(6)是调用ConcurrentAlloc,一次调6字节
创建线程
void TLSTest()
{
std::thread t1(Alloc1);
t1.join();
std::thread t2(Alloc2);
t2.join();
}
t1和t2是thread线程对象,这两个线程执行Alloc1和Alloc2,t1.john表示t1加入主线程
每个线程创建是并不是代表他立刻就有thread cache,而是调用相关的接口ConcurrentAlloc等