线程安全:无论有多少个线程调用这个函数,此函数都会给相应的线程返回正确的结果。
在进程中会维护一个表,里面共有128个键值,每个键值都有一个标志位(假如标志0为没占用,1为占用),还有析构函数。每个线程也对应一张表如上图。 先定义一个全局变量pthread_key_t mykey; 先调用这个函数int pthread_key_create(pthread_key_t *key, void (*destr_function) (void *));这个函数会给key设置一个没有用过的最小的键值,把响应标志位置位1,如上图就是分配的零。 然后传入键值,void * pthread_getspecific(pthread_key_t key);如果mykey之前没有被地址,这个函数会返回NUU。然后我们就可以创建一个指针P,给它申请空间,int pthread_setspecific(pthread_key_t key, const void *pointer);通过这个函数使P与键值进行绑定,下次就可以通过键值来使用线程申请的次有空间了。如果调用void * pthread_getspecific(pthread_key_t key);函数时,mykey已经绑定好键值了,那么就会这个函数就会返回键值所绑定的地址P。
另一个线程也是这样通过mykey得到0,但是“你的0”和“我的0”是不一样的,此0非彼0,他会拿到这个“0”通过int pthread_setspecific(pthread_key_t key, const void *pointer);通过这个函数使申请的Q空间与键值进行绑定。下次再调用void * pthread_getspecific(pthread_key_t key);函数时,mykey已经绑定好地址了,那么就会这个函数就会返回键值所绑定的地址Q。
还有一个最重要的是int pthread_key_create(pthread_key_t *key, void (*destr_function) (void *));这个函数只能调用一次,如果调用第二次的话会再设置一个没有用过的最小的键值,也就是1,这个key就不是我们需要的了。所以通过调用pthread_once_t once_control = PTHREAD_ONCE_INIT;int pthread_once(pthread_once_t *once_control, void (*init_routine) (void));这个函数使pthread_key_create只被运行一次。线程退出后会检测mykey的标志位有没有效,有效则调用析构函数来释放资源。 当然这个方法是适用于多线程的,单线程完全没有必要这样,只会花费更多的开销。所以我们可以通过编译宏的方式,来采用运行方式。gcc -o xxx xxx.c -lpthread -D__REENTRANT
还有一个方法就是定义rbuf是加上修饰__thread,这个方法好尼玛简单啊,但是有什么缺点就不做探讨了。当然,上面那个方法既然存在就有他的道理。