一、基本概念
线程局部存储(TLS),是一种变量的存储方法,这个变量在它所在的线程内是全局可访问的,但是不能被其他线程访问到,这样就保持了数据的线程独立性。而熟知的全局变量,是所有线程都可以访问的,这样就不可避免需要锁来控制,增加了控制成本和代码复杂度。
二、基本使用
环境:Visual studio
头文件:Windows.h
使用到的函数:TlsAlloc
,TlsSetValue
,TlsGetValue
,TlsFree
TlsAlloc函数:
函数原型:DWORD TlsAlloc();
作用:为调用该函数的线程分配一个线程局部存储序号,供其它三个函数使用
注意:一个进程最多分配TLS_MINIMUM_AVAILABLE个索引,目前定义为64,一个进程中所有线程分配的索引不会重复
使用:
int index=TlsAlloc()
TlsSetValue函数:
函数原型:BOOL TlsSetValue(DWORD dwTlsIndex,LPVOID lpTlsValue);
作用:在指定的序号内存储数据,如TlsAlloc分配成功返回的序号
使用:
BOOL ret=TlsSetValue(index,(LPVOID)0x123456)
TlsGetValue函数:
函数原型:LPVOID TlsGetValue(DWORD dwTlsIndex);
作用:取得指定序号内存储的数据
使用:
LPVOID lp=TlsGetValue(index);
TlsFree函数:
函数原型:BOOL TlsFree(DWORD dwTlsIndex);
作用:释放指定序号
使用:
TlsFree(index);
三、例子
#include<iostream>
#include<Windows.h>
using namespace std;
LPVOID fun(int ind) {
return TlsGetValue(ind);
}
DWORD WINAPI testThr(LPVOID lpThreadParameter) {
int ind = (int)lpThreadParameter;
cout << "另启线程调用fun函数获取:" << fun(ind) << endl;
return 0;
}
int main() {
DWORD index = TlsAlloc(); //分配一个TLS索引
BOOL ret = TlsSetValue(index, (LPVOID)0x123456); //设置该索引的值为0x123456
LPVOID p=TlsGetValue(index); //根据该索引获取该值
cout << "主线程Main函数中:" << p << endl; //输出该值
cout << "主线程调用fun函数:" << fun(index) << endl; //调用fun函数获取该值
HANDLE hThr=CreateThread(NULL,0, testThr,(LPVOID)index,NULL,NULL);//创建一个新线程,传入索引
WaitForSingleObject(hThr,5000); //等待新建线程结束
TlsFree(index); //释放该索引
}
运行结果:
分析:
以上代码,首先创建一个fun
函数,作用为根据传入的索引调用TlsGetValue
函数获取并返回该索引的值。
后在main
函数中调用TlsAlloc
分配一个TLS
索引,再调用TlsSetValue
设置该索引值为0x123456
,接着进行对比实验。
分别在主线程main
函数中直接调用TlsGetValue
获取,调用fun
函数获取,以及创建另一个线程调用fun
函数获取,并分别输出,可以看到,只有主线程能够获取到该值,另启动线程获取的值为0
总结
线程局部存储(TLS),可以存储只能该线程使用的数据。