线程特定数据

线程特定数据:
在单线程程序中,我们经常要用到“全局变量”以实现多个函数间共享数据。在多线程环境下,由于数据空间是共享的,因此
全局变量也为所有的线程所共享。但有的应用程序设计中有必要提供线程私有的全局变量,仅在某个线程中有效,但却可以跨越多个函数
访问。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;
}
原文地址:https://www.cnblogs.com/wsw-seu/p/8497169.html