Linux多线程实践(4)

线程特定数据int pthread_key_create(pthread_key_t *key, void (*destr_function) (void *));int pthread_key_delete(pthread_key_t key);int pthread_setspecific(pthread_key_t key, const void *pointer);void * pthread_getspecific(pthread_key_t key);pthread_once_t once_control = PTHREAD_ONCE_INIT;int pthread_once(pthread_once_t *once_control, void (*init_routine) (void));

在单线程程序中,我们经常要用到"全局变量"以实现多个函数间共享数据,然而在多线程环境下,由于数据空间是共享的,因此全局变量也为所有线程所共有。但有时应用程序设计中有必要提供线程私有的全局变量,,仅在某个线程中有效,但却可以跨多个函数访问。POSIX线程库通过维护一定的数据结构来解决这个问题,这个些数据称为(Thread-specific-data或TSD),线程特定数据如下图所示:

从上图可知:当调用pthread_key_create后会产生一个所有线程都可见的线程特定数据(TSD)的键值(如上图中所有的线程都会得到一个pkey[1]的值),但是这个键所指向的真实数据却是不同的,虽然都是pkey[1],但是他们并不是指向同一块内存,而是指向了只属于自己的实际数据,因此,如果线程0更改了pkey[1]所指向的数据,而并不能够影像到线程n;

在线程调用pthread_setspecific后会将每个线程的特定数据与thread_key_t绑定起来,虽然只有一个pthread_key_t,但每个线程的特定数据是独立的内存空间,当线程退出时会执行destructor函数。

/** 示例1: 设置/获取线程特定数据在两个线程中分别设置/获取线程特定数据, 查看两个线程中的数据是否是一样的(肯定是不一样的O(∩_∩)O~)**/pthread_key_t key;typedef struct Tsd{pthread_t tid;char *str;} tsd_t;//用来销毁每个线程所指向的实际数据void destructor_function(void *value){free(value);cout << "destructor …" << endl;}void *thread_routine(void *args){//设置线程特定数据tsd_t *value = (tsd_t *)malloc(sizeof(tsd_t));value->tid = pthread_self();value->str = (char *)args;pthread_setspecific(key, value);printf("%s setspecific, address: %p\n", (char *)args, value);//获取线程特定数据value = (tsd_t *)pthread_getspecific(key);printf("tid: 0x%x, str = %s\n", (unsigned int)value->tid, value->str);sleep(2);//再次获取线程特定数据value = (tsd_t *)pthread_getspecific(key);printf("tid: 0x%x, str = %s\n", (unsigned int)value->tid, value->str);pthread_exit(NULL);}int main(){//这样每个线程当中都会有一个key可用了,//但是每个key所绑定的实际区域需要每个线程自己指定pthread_key_create(&key, destructor_function);pthread_t tid1, tid2;pthread_create(&tid1, NULL, thread_routine, (void *)"thread1");pthread_create(&tid2, NULL, thread_routine, (void *)"thread2");pthread_join(tid1, NULL);pthread_join(tid2, NULL);pthread_key_delete(key);return 0;}/** 示例2:运用pthread_once, 让key只初始化一次注意: 将对key的初始化放入到init_routine中**/pthread_key_t key;pthread_once_t once_control = PTHREAD_ONCE_INIT;typedef struct Tsd{pthread_t tid;char *str;} tsd_t;//线程特定数据销毁函数,//用来销毁每个线程所指向的实际数据void destructor_function(void *value){free(value);cout << "destructor …" << endl;}//初始化函数, 将对key的初始化放入该函数中,//可以保证inti_routine函数只运行一次void init_routine(){pthread_key_create(&key, destructor_function);cout << "init…" << endl;}void *thread_routine(void *args){pthread_once(&once_control, init_routine);//设置线程特定数据tsd_t *value = (tsd_t *)malloc(sizeof(tsd_t));value->tid = pthread_self();value->str = (char *)args;pthread_setspecific(key, value);printf("%s setspecific, address: %p\n", (char *)args, value);//获取线程特定数据value = (tsd_t *)pthread_getspecific(key);printf("tid: 0x%x, str = %s\n", (unsigned int)value->tid, value->str);sleep(2);//再次获取线程特定数据value = (tsd_t *)pthread_getspecific(key);printf("tid: 0x%x, str = %s\n", (unsigned int)value->tid, value->str);pthread_exit(NULL);}int main(){pthread_t tid1, tid2;pthread_create(&tid1, NULL, thread_routine, (void *)"thread1");pthread_create(&tid2, NULL, thread_routine, (void *)"thread2");pthread_join(tid1, NULL);pthread_join(tid2, NULL);pthread_key_delete(key);return 0;}

(图1)

一定要成为你工作最大的资产。

Linux多线程实践(4)

相关文章:

你感兴趣的文章:

标签云: