2013-05-30 127 views
0

我正在重構現有的應用程序代碼。這次重組的一個要求是我需要存儲一個線程特定的變量,這個變量在閱讀和寫入時都會經常被引用。我會有大約50個這樣的線程。線程特定的變量基本上是一個指向結構的指針。 在這裏,我無法決定我應該如何存儲這個變量。我是否應該讓線程可以通過pthread_getspecific/pthread_setspecific訪問特定的密鑰?但我遇到一些帖子,說這些電話很慢。然後,另一種方法可以是具有全局結構,該全局結構將所有這些線程特定指針存儲在排序數組中(使用二進制搜索)或鍵值形式的元素哈希表。關鍵將大多是常量(thread_id),並且值可能會頻繁更改。再次,這裏最好的辦法是什麼? 我知道對所需值的最快訪問將實際上將此指針傳遞給每個函數並繼續傳播它。但是這需要很多我想避免的代碼重寫。 在此先感謝您的回覆。適當地存儲線程特定變量

回答

1

如果您使用的是gcc工具鏈(也包括其他一些編譯器),您可以選擇第三個選項。使用__thread存儲類說明符。這非常有效。它通過將線程本地存儲項隔離到單獨的VM頁面中來工作,該線程在調度線程時被切換。這樣每個線程都可以指向它自己的變量副本。成本只是每個線程計劃的一項操作,沒有其他方法的每鍵查找成本。

+0

這似乎是一個不錯的選擇,我會進一步探討它。 – labyrinth

0

我不明白。結構是否是針對線程的?你的指針指向哪一個? 如果是,那麼具有線程特定結構的問題是什麼?如果它是共享的(同時有50個線程!),你可以有一個全局變量,儘管同步可能會導致更新值的問題。 爲什麼你想要一個指向所有線程特定數據的指針?

+0

該結構不是線程特定的,因此使用指針。很確實會有同步問題。將不得不實施一些機制來克服它。 – labyrinth

+0

一旦數據發生變化,您就可以向所有線程廣播。控制互斥的廣播將導致一個線程段刷新值。例如, 「線程1 互斥1 關鍵部分 /*廣播部分 調用具有更新序列 */ 因爲每個線程都有自己的全球數據副本線程X,你可以使用共享內存也許。 – Suzuka

1

如果你的線程是靜態的(即是,你推出他們,他們不退出,除非程序退出),那麼你可以簡單地使用你所關心的任何映射結構。唯一的竅門是在允許所有線程運行之前,需要填充地圖。所以,你可能需要一個互斥和條件變量來阻塞所有的線程,直到地圖被填充。之後,你可以播放所有等待的線程去。由於地圖在此之後永遠不會改變,因此每個線程都可以從中讀取而不用任何爭用來檢索其線程特定信息。

如果您使用的是GCC,那麼您可以使用編譯器特定的擴展名。 __thread存儲類擴展在線程特定區域中放置了一個全局變量,以便每個線程都有自己的全局副本。

__thread struct info_type *info; 
1

在做任何事情之前,不要過早優化,測量標準方法的性能。它們不應該平均使用超過100個時鐘週期來爲您提供線程指定指針。在許多應用中,這與噪音沒有多大區別。

然後,我懷疑任何便攜式解決方案,你可以來與去通過某種全局變量或函數可以比POSIX功能更快。基本上他們沒有比你提出的更多的東西,但可能更好的優化。

,你所擁有的最好的辦法是實現每個線程的堆棧上的數據,並通過給需要它的功能將指針傳遞數據。

如果你有一個符合C11的編譯器(我認爲clang已經實現了這個部分),你可以使用_Thread構造,它提供了你想要的變量類型。其他編譯器(C11之前的版本)具有這些擴展的特徵,例如, gcc系列編譯器使用__thread