muduo網路庫學習筆記(7):執行緒特定資料

li27z發表於2016-09-04

(1)瞭解執行緒特定資料
在單執行緒程式中,我們經常要用到“全域性變數”以實現多個函式間共享資料。在多執行緒環境下,由於資料空間是共享的,因此全域性變數也為所有執行緒所共有。但有時應用程式設計中有必要提供執行緒私有的全域性變數,僅在某個執行緒中有效,但卻可以跨多個函式訪問。POSIX執行緒庫通過維護一定的資料結構來解決這個問題,這個資料稱為Thread-specific Data或 TSD。執行緒特定資料也稱為執行緒本地儲存TLS(Thread-local storage)。

對於POD型別的執行緒本地儲存,可以用__thread關鍵字;對於非POD型別的執行緒本地儲存,可以用TSD來解決。

(2)執行緒特定資料的用法
第一步,建立一個型別為 pthread_key_t 型別的變數。

第二步,呼叫 pthread_key_create() 來建立該變數。該函式有兩個引數,第一個引數就是上面宣告的 pthread_key_t 變數,第二個引數是一個清理函式,用來線上程釋放該執行緒儲存的時候被呼叫。該函式指標可以設成 NULL ,這樣系統將呼叫預設的清理函式。

當執行緒中需要儲存特殊值的時候,可以呼叫 pthread_setspecific() ,該函式有兩個引數,第一個為前面宣告的 pthread_key_t 變數,第二個為 void* 變數,這樣你可以儲存任何型別的值。

如果需要取出所儲存的值,呼叫 pthread_getspecific() ,該函式的引數為前面提到的 pthread_key_t 變數,該函式返回 void * 型別的值。

函式原型如下:

#include <pthread.h>

int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));

int pthread_key_delete(pthread_key_t key);

int pthread_setspecific(pthread_key_t key, const void *value);

void *pthread_getspecific(pthread_key_t key);

(3)部分程式碼分析
類圖:
這裡寫圖片描述

執行緒特定資料的資料結構:
這裡寫圖片描述

檔名:ThreadLocal.h

// 返回實際資料
// 先判定指標是否為空,為空就建立該資料並設定,不為空則直接返回該資料
T& value()
{
    T* perThreadValue = static_cast<T*>
                              (pthread_getspecific(pkey_));    
    if (!perThreadValue) {
      T* newObj = new T();
      pthread_setspecific(pkey_, newObj);
      perThreadValue = newObj;
    }
    return *perThreadValue;
}
檔名:ThreadLocal.h

// pthread_key_create函式中設定的清理函式,用來銷燬實際資料
static void destructor(void *x)
{
    T* obj = static_cast<T*>(x);
    typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1];  // 檢測是否是完全型別
    delete obj;
}

相關文章