1. 程式人生 > >執行緒私有資料

執行緒私有資料

    在參考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);

}