概念及作用
线程私有数据(thread-specify data,TSD)类似于全局变量,可以跨函数使用,区别是TSD是线程私有的。
创建和注销
int pthread_key_create(pthread_key_t *key, void (*destr_func)(void *))
key,函数从TSD池中分配一项,所创建的是所有线程都能访问的,但各个线程可以根据自己需要往key中写填不同的值,相当于提供了一个同名但不同值的全局变量。
destr,线程退出时,调用destr_func函数,释放分配的内存。但是如果在线程退出前,调用了pthread_key_delete函数,那么已退出线程的destr_func函数永远不会被调用了,所以应确保所有使用key的线程退出后,调用pthread_key_delete函数。一般可以在主线程等待所有线程退出后,调用pthread_key_delete函数。
int pthread_key_delete(pthread_key_t key)
这个函数并不检查是否有thread正在使用该TSD,也不会调用清理函数destr_func,而只是将TSD释放。
访问
int pthread_setspecific(pthread_key_t key, const void *p);
void pthread_getspecific(pthread_key_t key);
在LinuxThreads中,使用了一个位于线程描述结构(_pthread_descr_struct)中的二维void *指针数组来存放与key关联的数据,数组大小由以下几个宏来说明:
#define PTHREAD_KEY_2NDLEVEL_SIZE 32 #define PTHREAD_KEY_1STLEVEL_SIZE / ((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1) / PTHREAD_KEY_2NDLEVEL_SIZE) 其中在/usr/include/bits/local_lim.h中定义了PTHREAD_KEYS_MAX为1024, 因此一维数组大小为32。而具体存放的位置由key值经过以下计算得到: idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE |
也就是说,数据存放与一个32×32的稀疏矩阵中。同样,访问的时候也由key值经过类似计算得到数据所在位置索引,再取出其中内容返回。