日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

TSD(Thread Specific Data)线程专有数据

發(fā)布時間:2024/4/15 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 TSD(Thread Specific Data)线程专有数据 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

(1)全局變量

(2)局部變量

(3)TSD(Thread-Specific Data 線程專有數(shù)據(jù))

1.http://upczap.itpub.net/

   在單線程的程序里,有兩種基本的數(shù)據(jù):全局變量和局部變量。但在多線程程序里,還有第三種數(shù)據(jù)類型:線程數(shù)據(jù)(TSD: Thread-Specific Data)。它和全局變量很象,在線程內(nèi)部,各個函數(shù)可以象使用全局變量一樣調(diào)用它,但它對線程外部的其它線程是不可見的。這種數(shù)據(jù)的必要性是顯而易見 的。例如我們常見的變量errno,它返回標(biāo)準(zhǔn)的出錯信息。它顯然不能是一個局部變量,幾乎每個函數(shù)都應(yīng)該可以調(diào)用它;但它又不能是一個全局變量,否則在 A線程里輸出的很可能是B線程的出錯信息。要實現(xiàn)諸如此類的變量,我們就必須使用線程數(shù)據(jù)。我們?yōu)槊總€線程數(shù)據(jù)創(chuàng)建一個鍵,它和這個鍵相關(guān)聯(lián),在各個線程 里,都使用這個鍵來指代線程數(shù)據(jù),但在不同的線程里,這個鍵代表的數(shù)據(jù)是不同的,在同一個線程里,它代表同樣的數(shù)據(jù)內(nèi)容。



2.http://bbs.chinaunix.net/viewthread.php?tid=941730

linux 多線程編程中引入了Thread-Specific Data(線程相關(guān)的數(shù)據(jù))的概念
為什么需要"線程相關(guān)的數(shù)據(jù)"呢?怎樣使用"線程相關(guān)的數(shù)據(jù)"呢?

1. 為什么需要Thread-Specific Data "線程相關(guān)的數(shù)據(jù)"

這里只介紹我個人認(rèn)為的一個原因, 當(dāng)然它還有許多其他用途,歡迎大家討論

例子:實現(xiàn)同時運(yùn)行兩個線程,對于每個線程,在該線程調(diào)用的每個函數(shù)中打印線程的名字,以及它正在調(diào)用的函數(shù)的名字.

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

不使用"線程相關(guān)的數(shù)據(jù)"的兩種實現(xiàn)方法:

實現(xiàn)方法1. 不使用全局變量

#include <string.h>
#include <pthread.h>
#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);
}


輸出結(jié)果為:
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

該方法的缺點(diǎn)是:由于要記錄是哪一個線程在調(diào)用函數(shù),每個函數(shù)需要一個額外的參數(shù)來
記錄線程的名字,例如another_func函數(shù)需要一個threadName參數(shù)
如果調(diào)用的函數(shù)多了,則每一個都需要一個這樣的參數(shù)

實現(xiàn)方法2. 使用全局變量

#include <string.h>
#include <pthread.h>
#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);
}


該方法的缺點(diǎn)是:由于多個線程需要讀寫全局變量threadName,就需要使用互斥機(jī)制

分析以上兩種實現(xiàn)方法,Thread-Specific Data "線程相關(guān)的數(shù)據(jù)"的一個好處就體現(xiàn)出來了:
(1)"線程相關(guān)的數(shù)據(jù)"可以是一個全局變量,并且
(2)每個線程存取的"線程相關(guān)的數(shù)據(jù)"是相互獨(dú)立的.


2. 怎樣使用"線程相關(guān)的數(shù)據(jù)"

這是利用"線程相關(guān)的數(shù)據(jù)"的實現(xiàn)方式:

#include <string.h>
#include <pthread.h>

pthread_key_t p_key;

void another_func ()
{
??printf ("%s is running in another_func/n", (char *)pthread_getspecific(p_key));
}

void * thread_func (void * args)
{
??pthread_setspecific(p_key, args);
??printf ("%s is running in thread_func/n", (char *)pthread_getspecific(p_key));
??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,就可以存取只跟當(dāng)前線程相關(guān)的一個值(這個值由編譯器管理)
線程A----->p_key----->線程A相關(guān)的值(由編譯器管理)
線程B----->p_key----->線程B相關(guān)的值(由編譯器管理)

設(shè)置"線程相關(guān)的數(shù)據(jù)",使用
int pthread_setspecific(pthread_key_t key, const void *pointer);
讀取"線程相關(guān)的數(shù)據(jù)",使用
void * pthread_getspecific(pthread_key_t key);

注意到,這兩個函數(shù)分別有一個void類型的指針,我們的線程就是通過這兩個指針分別與
"線程相關(guān)的數(shù)據(jù)"的數(shù)據(jù)進(jìn)行交互的

(2)
由于p_key是一個全局變量,
函數(shù)another_func不需要額外的參數(shù)就可以訪問它;
又因為它是"線程相關(guān)的數(shù)據(jù)", 線程A, B通過p_key存取的數(shù)據(jù)是相互獨(dú)立的,
這樣就不需要額外的互斥機(jī)制來保證數(shù)據(jù)訪問的正確性了.

總結(jié)

以上是生活随笔為你收集整理的TSD(Thread Specific Data)线程专有数据的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。