Posix執行緒程式設計指南 2 執行緒私有資料

2021-06-15 21:22:22 字數 2525 閱讀 2155

posix執行緒程式設計指南(2)——執行緒私有資料

級別: 初級

楊沙洲 ([email protected]

)引自:

2001 年 10 月 01 日

這是乙個關於posix執行緒程式設計的專欄。作者在闡明概念的基礎上,將向您詳細講述posix執行緒庫api。本文是第二篇將向您講述執行緒的私有資料。

概念及作用

在單執行緒程式中,我們經常要用到"全域性變數"以實現多個函式間共享資料。在多執行緒環境下,由於資料空間是共享的,因此全域性變數也為所有執行緒所共有。但有時應用程式設計中有必要提供執行緒私有的全域性變數,僅在某個執行緒中有效,但卻可以跨多個函式訪問,比如程式可能需要每個執行緒維護乙個鍊錶,而使用相同的函式操作,最簡單的辦法就是使用同名而不同變數位址的執行緒相關資料結構。這樣的資料結構可以由posix執行緒庫維護,稱為執行緒私有資料(thread-specific data,或tsd)。

建立和登出

posix定義了兩個api分別用來建立和登出tsd:

int pthread_key_create(pthread_key_t *key, void (*destr_function) (void *))
不論哪個執行緒呼叫pthread_key_create(),所建立的key都是所有執行緒可訪問的,但各個執行緒可根據自己的需要往key中填入不同的值,這就相當於提供了乙個同名而不同值的全域性變數。在linuxthreads的實現中,tsd池用乙個結構陣列表示:

static struct pthread_key_struct pthread_keys[pthread_keys_max] =  };
建立乙個tsd就相當於將結構陣列中的某一項設定為"in_use",並將其索引返回給*key,然後設定destructor函式為destr_function。

登出乙個tsd採用如下api:

int pthread_key_delete(pthread_key_t key)
這個函式並不檢查當前是否有執行緒正使用該tsd,也不會呼叫清理函式(destr_function),而只是將tsd釋放以供下一次呼叫pthread_key_create()使用。在linuxthreads中,它還會將與之相關的執行緒資料項設為null(見"訪問")。

訪問

tsd的讀寫都通過專門的posix thread函式進行,其api定義如下:

int  pthread_setspecific(pthread_key_t  key,  const   void  *pointer)
void * pthread_getspecific(pthread_key_t key)
寫入(pthread_setspecific())時,將pointer的值(不是所指的內容)與key相關聯,而相應的讀出函式則將與key相關聯的資料讀出來。資料型別都設為void *,因此可以指向任何型別的資料。

在linuxthreads中,使用了乙個位於執行緒描述結構(_pthread_descr_struct)中的二維void *指標陣列來存放與key關聯的資料,陣列大小由以下幾個巨集來說明:

#define pthread_key_2ndlevel_size       32

#define pthread_key_1stlevel_size /

((pthread_keys_max + pthread_key_2ndlevel_size - 1)

/ pthread_key_2ndlevel_size)

其中在/usr/include/bits/local_lim.h中定義了pthread_keys_max為1024,因此一維陣列大小為32。而具體存放的位置由key值經過以下計算得到:

idx1st = key / pthread_key_2ndlevel_size

idx2nd = key % pthread_key_2ndlevel_size

也就是說,資料存放與乙個32×32的稀疏矩陣中。同樣,訪問的時候也由key值經過類似計算得到資料所在位置索引,再取出其中內容返回。

使用範例

以下這個例子沒有什麼實際意義,只是說明如何使用,以及能夠使用這一機制達到儲存執行緒私有資料的目的。

#include 

#include

pthread_key_t key;

void echomsg(int t)

void * child1(void *arg)

void * child2(void *arg)

int main(void)

給例程建立兩個執行緒分別設定同乙個執行緒私有資料為自己的執行緒id,為了檢驗其私有性,程式錯開了兩個執行緒私有資料的寫入和讀出的時間,從程式執行結果可以看出,兩個執行緒對tsd的修改互不干擾。同時,當執行緒退出時,清理函式會自動執行,引數為tid。

關於作者

楊沙洲,男,現攻讀國防科大計算機學院計算機軟體方向博士學位。您可以通過電子郵件 [email protected]

跟他聯絡。

Posix執行緒程式設計指南 2

概念及作用 在單執行緒程式中,我們經常要用到 全域性變數 以實現多個函式間共享資料。在多執行緒環境下,由於資料空間是共享的,因此全域性變數也為所有執行緒所共有。但有時應用程式設計中有必要提供執行緒私有的全域性變數,僅在某個執行緒中有效,但卻可以跨多個函式訪問,比如程式可能需要每個執行緒維護乙個鍊錶,...

Posix執行緒程式設計指南 2

概念及作用 在單執行緒程式中,我們經常要用到 全域性變數 以實現多個函式間共享資料。在多執行緒環境下,由於資料空間是共享的,因此全域性變數也為所有執行緒所共有。但有時應用程式設計中有必要提供執行緒私有的全域性變數,僅在某個執行緒中有效,但卻可以跨多個函式訪問,比如程式可能需要每個執行緒維護乙個鍊錶,...

Posix執行緒程式設計指南 2 執行緒私有資料

概念及作用 在單執行緒程式中,我們經常要用到 全域性變數 以實現多個函式間共享資料。在多執行緒環境下,由於資料空間是共享的,因此全域性變數也為所有執行緒所共有。但有時應用程式設計中有必要提供執行緒私有的全域性變數,僅在某個執行緒中有效,但卻可以跨多個函式訪問,比如程式可能需要每個執行緒維護乙個鍊錶,...