pthread線程私有數據

     線程私有數據是存儲和查詢與某個線程相關的數據的一種機制。把這種數據稱爲線程私有/特定數據的原因是希望每個線程可以獨立地訪問數據副本而無需擔心數據同步問題。

    設計線程私有數據接口的原因是:(1).線程ID不能保證是小而連續的整數。例如上一章的程序threadid得到的結果:
main thread: pid 9508 tid 1611388704 (0x600bd720)
new thread:  pid 9508 tid 1603331840 (0x5f90e700)
    (2).它提供了基於進程的接口,又適應多線程環境的機制。一個明顯的例子是errno(每個線程都有自己的副本)。
    進程中的所有線程都可以訪問進程的整個地址空間,除了使用寄存器以外,線程沒有辦法阻止其他線程訪問它的數據,線程的私有數據也不例外。雖然底層實現並不能阻止這種訪問能力,但管理線程私有數據的函數可以提高線程間的數據獨立性。
(1).在分配線程私有數據之前,需要創建與該數據關聯的鍵。這個鍵將用於獲取對線程私有數據的訪問權。使用pthread_key_create創建一個鍵:
int pthread_key_create(pthread_key_t *keyp, void (*destructor)(void *));
int pthread_key_delete(pthread_key_t *key);
    創建的鍵存放在keyp指向的內存單元,這個鍵可以被進程中所有線程使用,但每個線程把這個鍵與不同的線程私有數據地址進行關聯。創建新建時,每個線程的數據地址設爲NULL。此外還可以爲該鍵關聯析構函數,僅正常退出時才調用,順序和鍵創建順序相同。如果線程調用了exit,_exit,_Exit,abort或者其他非正常退出時不會調用析構函數。通常線程通過使用malloc爲線程私有數據分配內存,析構函數free已經釋放的內存。pthread_key_delete用來取消鍵和線程的關聯。
(2).在多線程併發條件下,如果每個線程都包含同一個鍵創建程序會引發競爭。確保鍵的創建只出現一次,使用pthread_once函數。
pthread_once_t initflag = PTHREAD_ONCE_INIT;
int pthread_once(pthread_once_t *initflag, void (*initfn)(void));
initflag必須是一個全局或者靜態變量,而且必須初始化爲PTHREAD_ONCE_INIT。而void (*initfn)(void)是一個確保只能執行一次的函數。例如pthread_key_create:
 
  1. void destructor(void *); 
  2.  
  3. pthread_key_t key; 
  4. pthread_once_t initdone = PTHREAD_ONCE_INIT; 
  5.  
  6. void 
  7. thread_init(void
  8.     err = pthread_key_create(&key, destructor); 
  9.  
  10. int 
  11. threadfunc(void *arg) 
  12.     pthread_once(&init_done, thread_init); 
  13.     ...... 
鍵一旦創建,就可以通過pthread_setspecific函數把鍵和線程私有數據關聯出來,可以通過pthread_getspecific函數獲得線程私有數據地址。
void *pthread_getspecific(pthread_key_t key);
int pthread_setspecific(pthread_key_t key, const void *value);
/*pthread_getspecific返回空則沒有關聯,可做判斷*/
 
Textbook:
APUE
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章