1. 程式人生 > >【多執行緒程式設計】執行緒私有資料(TSD)

【多執行緒程式設計】執行緒私有資料(TSD)

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 )。