Thread-specific data(TSD)線程私有數據

Thread-specific data(TSD)線程私有數據

http://blog.chinaunix.net/uid-26885237-id-3209913.html  html

 

linux多線程編程中引入了Thread-Specific Data(線程相關的數據)的概念
爲何須要"線程相關的數據"呢?怎樣使用"線程相關的數據"呢?

1. 爲何須要Thread-Specific Data "線程相關的數據"

這裏只介紹我我的認爲的一個緣由, 固然它還有許多其餘用途,歡迎你們討論

例子:實現同時運行兩個線程,對於每一個線程,在該線程調用的每一個函數中打印線程的名字,以及它正在調用的函數的名字.

(下面的例子與實現只是爲了說明問題,有些地方可能不妥)

不使用"線程相關的數據"的兩種實現方法:

實現方法1. 經過傳參數,不使用全局變量
 
#include
#include
#define MAXLENGTH 20

void another_func (const char * threadName)
{
printf ("%s is running in another_func\n", threadName);
}

void * thread_func (void * args)
{
char threadName[MAXLENGTH];
strncpy (threadName, (char *)args, MAXLENGTH-1);

printf ("%s is running in thread_func\n", threadName);
another_func (threadName);

}

int main (int argc, char * argv[])
{

pthread_t pa, pb;
pthread_create ( &pa, NULL, thread_func, "Thread A");
pthread_create ( &pb, NULL, thread_func, "Thread B");

pthread_join (pa, NULL);
pthread_join (pb, NULL);
}

輸出結果爲:
Thread A is running in thread_func
Thread A is running in another_func
Thread B is running in thread_func
Thread B is running in another_func

該方法的缺點是:因爲要記錄是哪個線程在調用函數,每一個函數須要一個額外的參數來
記錄線程的名字,例如another_func函數須要一個threadName參數
若是調用的函數多了,則每個都須要一個這樣的參數

實現方法2. 使用全局變量,經過互斥
 
#include
#include
#define MAXLENGTH 20

char threadName[MAXLENGTH];
pthread_mutex_t sharedMutex=PTHREAD_MUTEX_INITIALIZER;

void another_func ()
{
printf ("%s is running in another_func\n", threadName);
}

void * thread_func (void * args)
{
pthread_mutex_lock(&sharedMutex);
strncpy (threadName, (char *)args, MAXLENGTH-1);
printf ("%s is running in thread_func\n", threadName);
another_func ();
pthread_mutex_unlock(&sharedMutex);

}

int main (int argc, char * argv[])
{

pthread_t pa, pb;
pthread_create ( &pa, NULL, thread_func, "Thread A");
pthread_create ( &pb, NULL, thread_func, "Thread B");

pthread_join (pa, NULL);
pthread_join (pb, NULL);
}

該方法的缺點是:因爲多個線程須要讀寫全局變量threadName,就須要使用互斥機制

分析以上兩種實現方法,Thread-Specific Data "線程相關的數據"的一個好處就體現出來了:
(1)"線程相關的數據"能夠是一個全局變量,而且
(2)每一個線程存取的"線程相關的數據"是相互獨立的.
 
2. 怎樣使用"線程相關的數據"

這是利用"線程相關的數據"的實現方式:
 
#include
#include

pthread_key_t p_key;

void another_func ()
{
printf ("%s is running in another_func\n", (char *)pthread_getspecific(p_key));//綁定私有數據以後,就可使用pthread_getspecific進行私有數據訪問了
}

void * thread_func (void * args)
{
pthread_setspecific(p_key, args);//在各線程中將私有數據與關鍵字進行綁定
printf ("%s is running in thread_func\n", (char *)pthread_getspecific(p_key));//綁定私有數據以後,就可使用pthread_getspecific進行私有數據訪問了
another_func ();

}

int main (int argc, char * argv[])
{

pthread_t pa, pb;

pthread_key_create(&p_key, NULL);//在主線程中建立關鍵字

pthread_create ( &pa, NULL, thread_func, "Thread A");
pthread_create ( &pb, NULL, thread_func, "Thread B");

pthread_join (pa, NULL);
pthread_join (pb, NULL);
}

說明:
(1)
線程A, B共用了p_key,
經過p_key,就能夠存取只跟當前線程相關的一個值(這個值由編譯器管理)
線程A----->p_key----->線程A相關的值(由編譯器管理)
線程B----->p_key----->線程B相關的值(由編譯器管理)

設置"線程相關的數據",使用
int pthread_setspecific(pthread_key_t key, const void *pointer);
讀取"線程相關的數據",使用
void * pthread_getspecific(pthread_key_t key);

注意到,這兩個函數分別有一個void類型的指針,咱們的線程就是經過這兩個指針分別與
"線程相關的數據"的數據進行交互的

(2)
因爲p_key是一個全局變量,
函數another_func不須要額外的參數就能夠訪問它;
又由於它是"線程相關的數據", 線程A, B經過p_key存取的數據是相互獨立的,
這樣就不須要額外的互斥機制來保證數據訪問的正確性了

 

================== Endlinux

相關文章
相關標籤/搜索