TLSAlloc()
缩写为TLS。进程中的全局变数与函式内定义的静态(static)变数,是各个执行绪都可以访问的共享变数。在一个执行绪修改的记忆体内容,对所有执行绪都生效。这是一个优点也是一个缺点。说它是优点,执行绪的数据交换变得非常快捷。说它是缺点,一个执行绪死掉了,其它执行绪也性命不保; 多个执行绪访问共享数据,需要昂贵的同步开销,也容易造成同步相关的BUG。
基本介绍
- 中文名:TLSAlloc()
- 缩写:TLS
- 性质:共享变数
- 特点:对所有执行绪都生效
简介
如果需要在一个执行绪内部的各个函式调用都能访问、但其它执行绪不能访问的变数(被称为static memory local to a thread 执行绪局部静态变数),就需要新的机制来实现。这就是TLS。
执行绪局部存储在不同的平台有不同的实现,可移植性不太好。幸好要实现执行绪局部存储并不难,最简单的办法就是建立一个全局表,通过当前执行绪ID去查询相应的数据,因为各个执行绪的ID不同,查到的数据自然也不同了。
大多数平台都提供了执行绪局部存储的方法,无需要我们自己去实现:
linux:
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);
Win32
方法一:每个执行绪创建时系统给它分配一个LPVOID指针的数组(叫做TLS数组),这个数组从C编程角度是隐藏着的不能直接访问,需要通过一些C API函式调用访问。首先定义一些DWORD执行绪全局变数或函式静态变数,準备作为各个执行绪访问自己的TLS数组的索引变数。一个执行绪使用TLS时,第一步线上程内调用TlsAlloc()函式,为一个TLS数组索引变数与这个执行绪的TLS数组的某个槽(slot)关联起来,例如获得一个索引变数:
global_dwTLSindex=TLSAlloc();
注意,此步之后,当前执行绪实际上访问的是这个TLS数组索引变数的执行绪内的拷贝版本。也就说,不同执行绪虽然看起来用的是同名的TLS数组索引变数,但实际上各个执行绪得到的可能是不同DWORD值。其意义在于,每个使用TLS的执行绪获得了一个DWORD类型的执行绪局部静态变数作为TLS数组的索引变数。C/C++原本没有直接定义执行绪局部静态变数的机制,所以在如此大费周折。
第二步,为当前执行绪动态分配一块记忆体区域(使用LocalAlloc()函式调用),然后把指向这块记忆体区域的指针放入TLS数组相应的槽中(使用TlsSetValue()函式调用)。
第三步,在当前执行绪的任何函式内,都可以通过TLS数组的索引变数,使用TlsGetValue()函式得到上一步的那块记忆体区域的指针,然后就可以进行记忆体区域的读写操作了。这就实现了在一个执行绪内部这个範围处处可访问的变数。
最后,如果不再需要上述执行绪局部静态变数,要动态释放掉这块记忆体区域(使用LocalFree()函式),然后从TLS数组中放弃对应的槽(使用TlsFree()函式)。
转载请注明出处海之美文 » TLSAlloc()