1. 程式人生 > >執行緒特定資料詳解

執行緒特定資料詳解

    執行緒特定資料,也被稱為執行緒私有資料,是一種儲存和查詢一個特定執行緒相關資料的機制。我們稱這個資料為執行緒特定或執行緒私有的原因,是因為每個執行緒訪問它自己獨立的資料拷貝,而不用擔心和其它執行緒的訪問的同步。

    執行緒特定資料看似很複雜,其實我們可以把它理解為就是一個索引指標。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);
        ...
    }
    ... 

}