zoukankan      html  css  js  c++  java
  • 线程特定数据详解

        线程特定数据,也被称为线程私有数据,是一种存储和查找一个特定线程相关数据的机制。我们称这个数据为线程特定或线程私有的原因,是因为每个线程访问它自己独立的数据拷贝,而不用担心和其它线程的访问的同步。

        线程特定数据看似很复杂,其实我们可以把它理解为就是一个索引指针。key结构中存储的是索引,pthread结构中存储的是指针,指向线程中的私有数据,通常是malloc函数返回的指针。

        POSIX要求实现POSIX的系统为每个进程维护一个称之为Key的结构数组(如图1所示),这个数组中的每个结构称之为一个线程特定数据元素。POSIX规定系统实现的Key结构数组必须包含不少于128个线程特定元素,而每个线程特定数据元素至少包含两项内容:使用标志和析构函数指针。key结构中的标志指示这个数组元素是否使用,所有的标志初始化为“不在使用”


        当一个线程调用pthread_key_create创建一个新的线程特定数据元素时,系统搜索其所在进程的Key结构数组,找出其中第一个未使用的元素,并通过keyptr返回该元素的键,即就是我们前面说的索引pthread_key_create函数的第二个参数destructor是一个函数指针,指向一个析构函数,用于线程结束以后的一些后期后期处理工作,析构函数的额参数就是线程特定数据的指针。

        除了进程范围内地的key结构数组外,系统还在进程中维护关于每个线程的线程结构,把这个特定于线程的结构称为pthread结构,它的部分内容是于key数组对应的指针数组(如图2所示),它的128个指针和进程中的128个可能的键(索引)是逐一关联的。指针指向的内存就是线程特有数据。


        下面看一个具体的过程,启动一个进程并创建了若干线程,其中一个线程(比如线程1),要申请线程私有数据,系统调用pthread_key_creat()在图1所示的key结构数组中找到第一个未用的元素,并把它的键,也就是看面说的索引(0-127),返回给调用者,假设返回的索引是1,线程之后通过pthrea_getspecific()调用获得本线程的pkey[1]值,返回的是一个空指针ptr = null,这个指针就是我们可以通过索引1使用的线程数据的首地址了,但是他现在为空,因此根据实际情况用malloc分配一快内存,在使用pthread_setspecific()调用将特定数据的指针指向刚才分配到内存区域。整个过程结束后key结构和pthread结构如图3所示,


    在操作线程特定数据时涉及到的函数调用有一下几个:

    #include <pthread.h>
    
    //成功返回0,失败返回错误号。
    
    int pthread_key_create(pthread_key_t *keyp, void (*destructor)(void *)); 
    
    
    
    //返回线程特定数据,或者如果没有值关联到这个关键字时返回NULL。 
    
    void *pthread_getspecific(pthread_key_t key); 
    
    //成功返回0,失败返回错误号。
    
    int pthread_setspecific(pthread_key_t key, const void *value); 
    
    pthread_once_t initflag = PTHREAD_ONCE_INIT;
     
    
    //成功返回0,失败返回错误码。
    
    int pthread_once(pthread_once_t *initflag, void (*initfn)(void)); 
    
     
    
    //成功返回0,失败返回错误号。
    
    int pthread_key_delete(pthread_key_t *key);


    线程特定数据的典型用法如下:

    void destructor(void *) 
    
    pthread_key_t key; 
    
    pthread_once_t init_done = PTHREAD_ONCE_INIT; 
    
    void 
    
    thread_init(void) 
    
    { 
    
        err = pthread_key_create(&key, destructor); 
    
    } 
    
    int threadfunc(void *arg) 
    
    { 
    
        pthread_once(&init_done, thread_init); 
        
        if( (ptr = pthread_getspecific(key)) == NULL ){
            ptr = malloc(len);
            pthread_setspecific(key,ptr);
            ...
        }
        ... 
    
    }




  • 相关阅读:
    飞入飞出效果
    【JSOI 2008】星球大战 Starwar
    POJ 1094 Sorting It All Out
    POJ 2728 Desert King
    【ZJOI 2008】树的统计 Count
    【SCOI 2009】生日快乐
    POJ 3580 SuperMemo
    POJ 1639 Picnic Planning
    POJ 2976 Dropping Tests
    SPOJ QTREE
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3249130.html
Copyright © 2011-2022 走看看