线程特定函数有以下三个
int pthread_key_create(pthread_key_t *key, void (*destr_function) (void *));
void *pthread_getspecific(pthread_key_t key);
int pthread_setspecific(pthread_key_t key, const void *value);
但是经常会和下面这个函数一起使用
int pthread_once(pthread_once_t *once_control,void (*init_routine)(void))
首先解析一下线程特定函数原理:
每个进程都会维护一个Key结构的结构数组,如图所示,标志位表面这个Key是否被占用,析构函数指针是在线程终止或者结束时,会调用该函数指针指向的函数。
Key结构体的作用:每次线程调用pthread_key_create函数以后,就会去该表中寻找一个标志位显示未占用的元素,填充标志位和析构函数,然后将元素索引作为键值返回出来。
每个线程会维护一个自己单独的线程信息表,其中有一块称之为pkey的数组,这个数组每个元素和Key数组中每个元素的下标是一一对应的。pkey数组中的元素只是一个指针,这个指针指向的就是每个线程自己特定数据的存放地址。并且元素中如果有指针,通常是动态分配的,所以后面要释放,这就是在Key结构体的析构函数指针中释放。
对应到API接口,就是
pthread_setspecific函数用来在pkey数组的指定下标元素中设置地址,也就是存放指向特定数据的指针。
pthread_getspecific函数用来得到pkey数组中指定元素内的值(也就是指针值)。
而pthread_once函数是保证在多个线程中只会被使用一次,也就是如果线程A使用这个函数了,那么其他线程在执行时就会跳过这个函数。
使用方法:
在分析完原理之后,我们可以发现Key结构体中每一个元素,其实对应线程中都有不同的pkey数组,所以只需要调用pthread_key_create函数一次,每个线程中就都可以使用一个自己线程的特定元素,所以会使用到pthread_once函数。
而且一个进程中最多Key结构体只能有128个元素,也就意味着每个线程所允许的特定数据的数量不能超过128个,这是规定好的。
就拿UDP中的程序为例
相当于只使用了一次 pthread_key_create函数,也就是创建了一个特定数据。
并且析构函数指针readline_destructor中释放的就是pkey中的元素指针。