线程本地存储(Thread Local Storage)

Posted liu6666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程本地存储(Thread Local Storage)相关的知识,希望对你有一定的参考价值。

如果一个变量是全局的,那么所有线程访问的是同一份,某一个线程对其修改会影响其他所有线程。如果我们需要一个变量在每个线程中都能访问,并且值在每个线程中互不影响,这就是TLS。

 

线程局部存储在不同平台有不同的实现,可移植性不好。线程局部存储不难实现,最简单的办法是建立一个全局表,通过当前线程ID去查询相应的数据,因为各个线程ID去查询相应的数据,因为各个线程的ID不同,查到的数据自然也不同。

 

分两种:

1.静态TLS

_declspec(thread) DWORD data=0;

声明了_declspec(thread)的变量,会为每一个线程创建一个单独的拷贝。

技术图片

 

2.动态TLS

 

 

TEB结构中,有个指针指向线程TLS数组,称为_tls_array,利用这个数组指针可以管理线程相关的局部变量,这个数组由TLS_MINIMUM_AVAILABLE个元素组成,在WINNT.H文件中该值被定义为64个。

 

TlsAlloc函数

DWORD WINAPI TlsAlloc(void);

系统对进程中的标志位进行检索并找到一个FREE标志,然后系统会将该标志从FREE改为INUSE并让TlsAlloc返回该标志位在位数组中的索引。

成功返回索引,失败返回TLS_OUT_OF_INDEXES。

 

TlsSetValue函数设置变量值

BOOL WINAPI TlsSetValue(
DWORD dwTlsIndex,     //索引值,表示在数组中的具体位置
LPVOID lpTlsValue     //要设置的值
);

 

当一个线程调用TlsSetValue函数成功时,他会修改自己的PVOID数组,但它无法修改另一个线程TLS值。

 

TlsGetValue函数获取变量值

LPVOID WINAPI TlsGetValue(
 DWORD  dwTlsIndex  //索引值,表示在数组中的具体位置
);

 

返回在索引为dwTlsIndex  的TLS元素中保存的值,TlsGetValue只会查看属于调用线程的数组。

 

以上是关于线程本地存储(Thread Local Storage)的主要内容,如果未能解决你的问题,请参考以下文章

销毁 thread_local 对象

transmittable-thread-local:解决线程池之间ThreadLocal本地变量传递的问题

TLS 线程本地存储

线程本地存储进程

Thread-Local Storage for C99

线程局部存储: gcc __thread与c++11 thread_local 关键字