线程特定数据:
在单线程程序中,我们经常要用到“全局变量”以实现多个函数间共享数据。在多线程环境下,由于数据空间是共享的,因此
全局变量也为所有的线程所共享。但有的应用程序设计中有必要提供线程私有的全局变量,仅在某个线程中有效,但却可以跨越多个函数
访问。POSIX线程库通过维护一定的数据结构来解决这个问题。
//每个线程都有这个key。但是指向的数据不是共享的,是特定的数据。
int pthread_key_create(pthread_key_t *keyp,void (*destructor)(void*));
取消键与线程特定数据的关联
int pthread_key_delete(pthread_key_t key);
只要有一个线程创建了一个key,那么所有的线程就都有了一个key.假设线程0创建了key[1],其他线程也得到了一个key[1],
每个线程都有一个key,但是每个线程的key都指向了每个线程特定的数据。
//获取或者设定线程特定数据
void* pthread_getspecific(pthread_key_t key);
int pthread_setspecific(pthread_key_t key,const void* value);
//把键和线程特定数据关联起来
void* pthread_getspecific(pthread_key_t key);
int pyhread_setspecific(pthread_key_t,const void* value);
pthread_once_t initflag=PTHREAD_ONCE_INIT 必须是一个全局变量或者静态变量
int pthread_once(pthread_once_t* initflag,void (*initfn)(void)) 第二个参数:函数的执行只在第一个线程中执行
#include<unistd.h> #include<sys/types.h> #include<fcntl.h> #include<sys/stat.h> #include<stdlib.h> #include<stdio.h> #include<errno.h> #include<pthread.h> #include<string.h> #define ERR_EXIT(m) do { perror(m); exit(EXIT_FAILURE); }while(0) pthread_key_t key_std; pthread_once_t initflag=PTHREAD_ONCE_INIT;//设置一个全局变量用于pthread_once //线程特定数据,自己设定,一个是线程ID,一个是指针。 typedef struct tsd { pthread_t tid; char* str; }tsd_t; //线程特定数据销毁函数,每个线程都调用 void destroy_routine(void* value) { printf("destroy ... "); free(value); } void once_routine(void) { pthread_key_create(&key_std,destroy_routine);//创建一个key.第二个参数是一个函数指针,表示如何销毁这个线程特定数据。 printf("key init... "); } //线程入口函数中调用once_routine来创建键值。每次创建新线程,都会进入线程入口函数,调用once_routine //但是使用了pthread_once的话 ,只会执行一个once_routine。 void * thread_routine(void* arg) { //如果我们把创建键值放到线程执行函数中,则需要调用pthread_once使得该键值创建只要执行一次 pthread_once(&initflag,once_routine); tsd_t *value=(tsd_t*)malloc(sizeof(tsd_t)); //构造线程特定数据 value->tid=pthread_self(); value->str=(char*)arg; //设置线程特定数据 pthread_setspecific(key_std,value); printf("%s setsepecific %p ",(char*)arg,value);//%p指针值 //通过key,获取设定的特定数据。 value=pthread_getspecific(key_std); printf("tid=0x%x str=%s ",(int)value->tid,value->str); //2个线程都到这睡眠。数据不会串改 sleep(2); printf("tid=0x%x str=%s ",(int)value->tid,value->str); return NULL; } int main(void) { // pthread_key_create(&key_std,destroy_routine);//每个线程退出都会调用destroy_routine。销毁两次 //每个线程都有这个key,但各自的值不同 pthread_t tid1; pthread_t tid2; pthread_create(&tid1,NULL,thread_routine,"thread1"); pthread_create(&tid2,NULL,thread_routine,"thread2");//每个线程结束,都会调用destroy_routine。 pthread_join(tid1,NULL); pthread_join(tid2,NULL); //线程结束删除key pthread_key_delete(key_std); return 0; }