线程私有数据

    在参考ptmalloc实现的时候,碰到了一个新东西——线程私有数据,其数据是这样声明的 static tsd_key_t arena_key;。由于ptmalloc中的许多数据结构都是在内部重新定义的,而我手中的这部分源代码并不是完全的,所以我只好在网上查询tsd_key_t这个数据类型是什么。

    TSD(Thread-specific Data)这是tsd的全称,但是网上的内容并没有让我解惑,接着我又在书中《UNIX环境高级编程第二版》查阅了这部分的知识,下面我就来介绍一下这个线程私有数据是什么东西。

    我们知道线程共享进程中的所有数据和属性,这是线程的一个非常重要的特点,而且使我们设计线程这种模型一个很重要的原因。但是这有一个问题,有时候需要维护基于每个线程的数据,但因为线程ID并不能保证是一个小而连续的整数,所以不能简单的分配一个基于线程ID的数据组,以线程ID作为索引,而且就算线程ID是小而连续的整数,我们也希望有一些额外的保护。在我遇到的问题中,内存分配有一个主分配区,多个非主分配区,我们并不希望所有的线程都在一个分配区内分配(毕竟那样的效率很低),所以就引出了线程私有数据这样一个问题。

    下面我们来说一下如何分配私有数据,在这之前我将在源码中遇到的相关的代码贴出来:

        static tsd_key_t arena_key;

        tsd_key_create(&arena_key, NULL); 

        tsd_setspecific(arena_key, (Void_t *)&main_arena);

        tsd_getspecific(arena_key, vptr);

在分配私有数据之前,我们需要创建一个与之关联的键(key),而在创建这个键之前我们需要声明这个变量

#include <pthread.h>//这个头文件在linux下

        pthread_key_t key;

接下来是创建这个键的函数签名:

        int pthread_key_create(pthread_key_t *key , void(*destractor)(void*));//成功返回0,失败返回错误编号

    创建的键存放在key指针所指向的内存单元中,第二个参数是其相关的析构函数,可以为NULL(就像我遇到的一样)表明没有析构函数,当线程正常退出时调用析构函数。可以调用int pthread_key_delete(pthread_key_t*key)来取消线程私有数据和键之间的关系,成功返回0,失败返回错误编号。

    关联这个键,和通过这个键获得私有数据的地址:

   通过 void * pthread_setspecific(pthread_key_t key , const void *value);//成功返回0,失败返回错误编号    来关联私有数据值和我们的键。

    通过    void* pthread_getspecific(pthread_key_t key);//私有数据的数据值,没有返回NULL    来获取某个键的私有数据值,可以看出我遇到的函数是经过封装的。

    最后,为了避免在创建键的时候出现竞争,我们介绍一个函数来解决这个问题:

       pthread_once_t iniflat = PTHREAD_ONCE_INIT;

        int pthread_once(phread_once_t *iniflag , void(*initfn(void));

    上面这个函数的第一个参数就不赘述了,说一下第二个参数,这个函数指针指向的就是类似下面的函数

    void thread_init(void)

{

    err = pthread_key_ceate(&key,destructor);

}


猜你喜欢

转载自blog.csdn.net/qq_35508286/article/details/79909100