POSIX线程的私有数据


多线程环境下,数据空间由所有线程共享。所以,一般意义上的全局变量也为所有的线程所共享。

有时需要提供线程私有的全局变量:
- 可以跨多个函数访问(全局);
- 仅在某个线程有效(私有)。

比如程序可能需要每个线程都维护一个链表,维护手段相同,链表内的数据却不同。

这样的数据结构可由POSIX线程库维护,称为Thread Specific Data,简称TSD。

  1. #ifdef WIN32   
  2.     #include <windows.h>   
  3.     #define SLEEP(ms) Sleep(ms)   
  4. #else if defined(LINUX)   
  5.     #include <stdio.h>   
  6.     #define SLEEP(ms) sleep(ms)   
  7. #endif   
  8.   
  9. #include <pthread.h>   
  10.   
  11. pthread_key_t key;  
  12.   
  13. void echomsg(void * value)  
  14. {  
  15.     printf("[CHILD THREAD] Destructor excuted, param=%s\n", (char *)value);  
  16. }  
  17.   
  18. void * child1(void *arg)  
  19. {  
  20.     printf("[CHILD THREAD - 1] Thread enter\n");  
  21.     pthread_setspecific(key, arg);  
  22.     SLEEP(2);  
  23.     printf("[CHILD THREAD - 1] Thread returns %s\n", (char *)pthread_getspecific(key));  
  24.     pthread_exit(NULL);  
  25.     return NULL;  
  26. }  
  27.   
  28. void * child2(void *arg)  
  29. {  
  30.     printf("[CHILD THREAD - 2] Thread enter\n");  
  31.     pthread_setspecific(key, arg);  
  32.     SLEEP(1);  
  33.     printf("[CHILD THREAD - 2] Thread returns %s\n", (char *)pthread_getspecific(key));  
  34.     return NULL;  
  35. }  
  36.   
  37. static const char * msg[2] =  
  38. {  
  39.     "Lazy cat",  
  40.     "Brown dog"  
  41. };  
  42.   
  43. int main(int argc, char* argv[])  
  44. {  
  45.     printf("[MAIN THREAD] Hello\n");  
  46.   
  47.     pthread_key_create(&key, echomsg);  
  48.   
  49.     pthread_t tid1,tid2;  
  50.     pthread_create(&tid1, NULL, child1, (void *)msg[0]);  
  51.     pthread_create(&tid2, NULL, child2, (void *)msg[1]);  
  52.   
  53.     pthread_join(tid1, NULL);  
  54.     pthread_join(tid2, NULL);  
  55.     pthread_key_delete(key);  
  56.   
  57.     printf("[MAIN THREAD] Exit\n");  
  58.     return 0;  
  59. }  
● 创建
int pthread_key_create (pthread_key_t * key, void (*destructor) (void *))

在Linux中,TSD池用一个结构数组实现:
static struct pthread_key_struct pthread_keys[PTHREAD_KEYS_MAX] = {{0, NULL}};

创建一个TSD就相当于将结构数组中的某一项设置为"in use"状态,并将其索引返回给*key,然后设置destructor函数。

从中也可以看出,TSD的数目有上限:PTHREAD_KEYS_MAX。定义于/usr/include/bits/local_lim.h,一般为1024。

不要在destructor里调用pthread_exit函数。

● 注销
int pthread_key_delete (pthread_key_t key)

该函数并不检查当前是否有线程正使用该TSD,也不会调用清理函数(destructor),只是将TSD释放以供下一次pthread_key_create()使用。
在LinuxThreads中,它还会将与之相关的线程数据项设为NULL。

● 读写
int pthread_setspecific (pthread_key_t key, const void *value)
void * pthread_getspecific (pthread_key_t key)

相关内容