【多執行緒程式設計】執行緒私有資料(TSD)
阿新 • • 發佈:2019-01-28
Thread Specific Data(TSD)
執行緒私有資料,有什麼用呢?在多執行緒中,經常要用全域性變數來實現多個函式間的資料共享。由於資料空間是共享的,因此全域性變數也為所有程序共有。但有時應用程式設計中必要提供執行緒私有的全域性變數,這個變數被各個執行緒私有,但卻可以跨過多個函式訪問。
書上是這樣說的:
int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));
該函式有兩個引數,第一個引數是 pthread_key_t 變數指標,第二個引數是一個解構函式指標,線上程釋放該執行緒儲存時被呼叫,該函式指標可以設成 NULL,這樣系統將呼叫預設的解構函式。解構函式正常返回0,其他任何返回值都表示出現了錯誤。另外還有:
int pthread_setspecific(pthread_key_t key, const void *value);
當執行緒中需要儲存特殊值的時候,可以呼叫 pthread_setspcific() 。該函式有兩個引數,第一個為前面宣告的pthread_key_t變數,第二個為void*變數,這樣你可以儲存任何型別的值。
void *pthread_getspecific(pthread_key_t key);
如果需要取出所儲存的值,呼叫pthread_getspecific()。該函式的引數為前面提到的pthread_key_t變數,該函式返回void *型別的值。下面用例子來說明:
#include <stdio.h> #include <pthread.h> pthread_key_t key; pthread_once_t once = PTHREAD_ONCE_INIT; // pthread_once 保證 create_key 只被執行一次 void create_key() { printf("init pthread_key\n"); if (pthread_key_create(&key, NULL)) { printf("pthread_key_create failed"); } } void display() { printf("I'm %u\n", *(int *)pthread_getspecific(key)); } void * worker(void *arg) { pthread_once(&once, create_key); pthread_t pid = pthread_self(); pthread_setspecific(key, &pid); printf("%x %x\n", &pid, (int *)pthread_getspecific(key)); display(); } int main() { pthread_t tid1, tid2; pthread_create(&tid1, NULL, worker, NULL); pthread_create(&tid2, NULL, worker, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); pthread_key_delete(key); return 0; }
輸出如下:
init pthread_key
9c6e5f40 9c6e5f40
I'm 2624481024
9bee4f40 9bee4f40
I'm 2616088320
pthread_getspecific() 返回的是與key 相關聯資料的指標。需要注意的是,在利用這個返回的指標時,它首先是 void 型別的,它雖然指向關聯的資料地址處,但並不知道指向的資料型別,所以在具體使用時,要對其進行強制型別轉換。其次,兩個執行緒對自己的私有資料操作是互相不影響的。也就是說,雖然 key 是同名且全域性,但訪問的記憶體空間並不是相同的一個。此外,各執行緒可以用 key 繫結不同型別的資料(我這裡都繫結的 int )。