文章來源自pthread_key_t和pthread_key_create()詳解
下面說一下線程中特有的線程存儲, Thread Specific Data
。線程存儲有什么用了?他是什么意思了?大家都知道,在多線程程序中,所有線程共享程序中的變量。現在有一全局變量,所有線程都可以使用它,改變它的值。而如果每個線程希望能單獨擁有它,那么就需要使用線程存儲了。表面上看起來這是一個全局變量,所有線程都可以使用它,而它的值在每一個線程中又是單獨存儲的。這就是線程存儲的意義。
下面說一下線程存儲的具體用法。
創建一個類型為
pthread_key_t
類型的變量。調用
pthread_key_create()
來創建該變量。該函數有兩個參數,第一個參數就是上面聲明的pthread_key_t
變量,第二個參數是一個清理函數,用來在線程釋放該線程存儲的時候被調用。該函數指針可以設成NULL
,這樣系統將調用默認的清理函數。該函數成功返回0.其他任何返回值都表示出現了錯誤。當線程中需要存儲特殊值的時候,可以調用
pthread_setspcific()
。該函數有兩個參數,第一個為前面聲明的pthread_key_t
變量,第二個為void*
變量,這樣你可以存儲任何類型的值。如果需要取出所存儲的值,調用
pthread_getspecific()
。該函數的參數為前面提到的pthread_key_t
變量,該函數返回void *
類型的值。下面是前面提到的函數的原型:
int pthread_setspecific(pthread_key_t key, const void *value);
void *pthread_getspecific(pthread_key_t key);
int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));
下面是一個如何使用線程存儲的例子:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
pthread_key_t key; // 好吧,這個玩意究竟是干什么的呢?
struct test_struct { // 用于測試的結構
int i;
float k;
};
void *child1(void *arg)
{
struct test_struct struct_data; // 首先構建一個新的結構
struct_data.i = 10;
struct_data.k = 3.1415;
pthread_setspecific(key, &struct_data); // 設置對應的東西嗎?
printf("child1--address of struct_data is --> 0x%p\n", &(struct_data));
printf("child1--from pthread_getspecific(key) get the pointer and it points to --> 0x%p\n", (struct test_struct *)pthread_getspecific(key));
printf("child1--from pthread_getspecific(key) get the pointer and print it's content:\nstruct_data.i:%d\nstruct_data.k: %f\n",
((struct test_struct *)pthread_getspecific(key))->i, ((struct test_struct *)pthread_getspecific(key))->k);
printf("------------------------------------------------------\n");
}
void *child2(void *arg)
{
int temp = 20;
sleep(2);
printf("child2--temp's address is 0x%p\n", &temp);
pthread_setspecific(key, &temp); // 好吧,原來這個函數這么簡單
printf("child2--from pthread_getspecific(key) get the pointer and it points to --> 0x%p\n", (int *)pthread_getspecific(key));
printf("child2--from pthread_getspecific(key) get the pointer and print it's content --> temp:%d\n", *((int *)pthread_getspecific(key)));
}
int main(void)
{
pthread_t tid1, tid2;
pthread_key_create(&key, NULL); // 這里是構建一個pthread_key_t類型,確實是相當于一個key
pthread_create(&tid1, NULL, child1, NULL);
pthread_create(&tid2, NULL, child2, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pthread_key_delete(key);
return (0);
}
看一下輸出的結果:
child1--address of struct_data is --> 0x0x7ffff77eff40
child1--from pthread_getspecific(key) get the pointer and it points to --> 0x0x7ffff77eff40
child1--from pthread_getspecific(key) get the pointer and print it's content:
struct_data.i:10
struct_data.k: 3.141500
------------------------------------------------------
child2--temp's address is 0x0x7ffff6feef44
child2--from pthread_getspecific(key) get the pointer and it points to --> 0x0x7ffff6feef44
child2--from pthread_getspecific(key) get the pointer and print it's content --> temp:20
非常有意思呢。