2011-03-04 35 views
1

所有線程共享內存位置。例如,一個線程中的全局變量更改將反映在另一個線程中。由於每個線程都有自己的堆棧,因此在線程內創建的本地變量是唯一的。在這種情況下,爲什麼我們需要 去尋找線程特定的數據機制呢?不能通過線程函數裏面的自動存儲變量 來實現嗎?爲什麼在pthread中需要線程特定的數據?

請澄清!!!

BR RJ

+0

所有全局變量默認在所有線程之間共享。 IIRC,可以使用線程特定的數據來指定,否則其中變量具有相同的名稱但是線程特定的。 – Kakira

回答

0

是,堆棧分配線程本地存儲(包括手柄,以堆分配本地的特定線程)的一種方式。

3

線程之間共享正常全局變量。局部變量特定於特定的函數調用。如果你想要的東西(例如)對同一個線程中運行的許多函數是可見的,但對於那個線程來說是唯一的,那麼線程特定的數據就是你正在尋找的東西。

1

這不是要求但它很方便。一些函數如randstrtok使用靜態存儲持續時間信息,這些信息在線程之間共享時可能會出現問題。

假設你有一個隨機數函數,你想爲每個線程維護一個不同的序列(因此種子)。你有兩種方法。

您可以使用類似的缺憾:

int seed; 
srand (&seed, time (NULL)); 
int r = rand_r (void *seed); 

其中種子必須由調用者創建和每次時間過去了。

或者您可以使用要好得多,符合ISO標準的:

srand (time (NULL)); 
int r = rand(); 

使用線程本地存儲以維持特定線程的種子。與strtok有關正在處理的字符串中的位置使用的信息類似。

這樣,您就不必在改變線程和非線程版本之間的代碼。

現在你可能在線程函數中創建信息,但rand函數如何知道它的地址而不傳遞它。那麼如果rand被稱爲87堆棧級別呢?這是一個可怕的很多級別傳遞指針。

而且,即使你做這樣的事情:

void pthread_fn (void *unused) { 
    int seed; 
    rand_set_seed_location (&seed); 
    : 
} 

rand隨後使用該值,無論它是在棧有多深,這仍然與標準中的代碼更改。它可能會工作,但可能會編寫COBOL中的操作系統。這不會讓一個好主意:-)

0

線程特定數據的最佳例子是「錯誤號」。當c庫中某個函數的調用失敗時,將設置errno,您可以檢查它以找出失敗的原因。如果沒有線程特定的數據,將這些函數移植到多線程環境是不可能的,因爲在您檢查它之前,其他線程可能會設置它們。

+0

但你如何保持線程特定數據中的errno? – user504542

+0

glibc中的errno是通過線程特定的數據實現的,我們只是使用它,不用擔心爭用。 – burningice

0

作爲一般規則,在新的API中應避免大多數TSD的使用。如果一個函數需要一些信息,它應該傳遞給它。

但是,有時您需要TSD來「覆蓋」API缺陷。一個很好的例子是'gmtime'。 'gmtime'函數返回一個指向有效的結構的指針,直到下一次調用'gmtime'。但是這會使'gmtime'在多線程程序中非常難以使用。如果某個圖書館在你沒有預料到的時候稱爲'gmtime'會怎樣,摧毀你的結構?一個簡單的解決方法是使結構返回線程特定的。 (當然,長期解決方案是創建更適合的API,例如'gmtime_r')。

在新設計中使用TSD完全合理的一種情況是不會頻繁訪問的信息這會混淆API。例如,如果發現嚴重錯誤,那麼記錄來自高級代碼的某些上下文信息可能會更好(您提供哪個客戶端?他們發送了什麼命令?)。你的選擇基本上是把這個上下文信息從功能傳遞到功能(如果某些功能不在你的控制範圍內,甚至不可能),或者把它存儲在TSD中。

相關問題