【C/C++多執行緒程式設計之十】pthread執行緒私有資料

Love_Hulidear發表於2014-05-04

多執行緒程式設計之執行緒私有資料


     Pthread是 POSIX threads 的簡稱,是POSIX的執行緒標準
        執行緒同步從互斥量【C/C++多執行緒程式設計之六】pthread互斥量訊號量【C/C++多執行緒程式設計之七】pthread訊號量,條件變數【C/C++多執行緒程式設計之八】pthread條件變數,讀寫鎖【C/C++多執行緒程式設計之九】pthread讀寫鎖多執行緒的同步機制已經有了清晰深入的探究,多執行緒程式設計的精髓所在,需要深入理解。
       執行緒私有資料TSD(Thread-specific Data),在【C/C++多執行緒程式設計之五】pthread執行緒深入理解中有提及,程式全域性變數是被所有執行緒共享的,處於功能與安全的需求,有必要為執行緒提供執行緒全域性變數。執行緒全域性變數便是執行緒私有資料,僅在某個執行緒內有效。
       
            1. 執行緒私有資料

        執行緒私有資料通過關聯的鍵值key識別,建立時將私有資料與key關聯,通過key向執行緒私有資料寫入內容,也通過key讀取執行緒私有資料的內容,最後通過key 刪除執行緒私有資料。 
        執行緒私有資料建立後,該程式內所有的執行緒都可以使用這個key向執行緒私有資料寫入與讀取資料。對不同的執行緒而言,同一個key值,分別訪問執行緒自己的私有資料,互不影響。
        舉例:
        建立關聯key的執行緒私有資料後,每個執行緒都有一份對應的執行緒私有資料。
        執行緒A通過key訪問執行緒A中的對應的執行緒私有資料。
        執行緒B通過key訪問執行緒B中的對應的執行緒私有資料。

        2.執行緒私有資料基本函式
        #include<pthread.h>
建立執行緒私有資料
        int pthread_key_create(pthread_key_t *key, void (*destr_function) (void *));
        該函式的第一個引數為鍵值key,第二個引數為銷燬函式(一般設為NULL,不為空時,銷燬執行緒私有資料時,會呼叫該函式以釋放分配的記憶體)。
寫入資料
        int pthread_setspecific(pthread_key_t  key,  void  *pointer);
        該函式的第一個引數為鍵值key,第二個引數為寫入資料指標(該指標型別為void* ,可以寫入指向任何資料型別的指標)。pointer寫入的是這個指標的值,而不是pointer指向的內容。
讀取資料
        void * pthread_getspecific(pthread_key_t key);
        該函式的引數為鍵值key,返回寫入的資料。
銷燬執行緒私有資料
        int pthread_key_delete(pthread_key_t key);
        該函式的引數為鍵值key,用於銷燬執行緒私有資料。

        3.牛刀小試:
        執行緒child1,child2均把自己的執行緒ID寫入自己的執行緒私有資料中,寫入的是一個指標,在讀出的資料是void *型的指標,需要對其進行強制型別轉換。
#include 
#include 
#include 
#include 
#pragma comment(lib, "pthreadVC2.lib")     //必須加上這句
pthread_key_t   key;
pthread_mutex_t mutex;
pthread_t tid1,*p1;
pthread_t tid2,*p2;
void * child1(void *arg)
{
        p1=&tid1;
        pthread_setspecific(key,p1);       //將執行緒id寫入執行緒私有資料
        p1=(pthread_t *)pthread_getspecific(key);   //讀取執行緒私有資料
        printf("執行緒child1 的私有資料: %d\n",*p1);
        return NULL;
}
void * child2(void *arg)
{
        p2=&tid2;
        pthread_setspecific(key,p2);       //將執行緒id寫入執行緒私有資料
        p2=(pthread_t *)pthread_getspecific(key);    //讀取執行緒私有資料
        printf("執行緒child2的私有資料:%d",*p2);
        Sleep(500);
        return NULL;
}
int main(void)
{
        pthread_key_create(&key,NULL);      //建立執行緒私有資料
        pthread_create(&tid1,NULL,child1,NULL);
        pthread_create(&tid2,NULL,child2,NULL);
        Sleep(100000);
        pthread_key_delete(key);            //銷燬執行緒私有資料
        return 0;
}

      

相關文章