日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Posix線程編程指南(2)

 omcc 2011-01-10

2001 年 10 月 01 日

這是一個關于Posix線程編程的專欄。作者在闡明概念的基礎上,將向您詳細講述Posix線程庫API。本文是第二篇將向您講述線程的私有數據。

概念及作用

在單線程程序中,我們經常要用到"全局變量"以實現多個函數間共享數據。在多線程環(huán)境下,由于數據空間是共享的,因此全局變量也為所有線程所共有。但有時應用程序設計中有必要提供線程私有的全局變量,僅在某個線程中有效,但卻可以跨多個函數訪問,比如程序可能需要每個線程維護一個鏈表,而使用相同的函數操作,最簡單的辦法就是使用同名而不同變量地址的線程相關數據結構。這樣的數據結構可以由Posix線程庫維護,稱為線程私有數據(Thread-specific Data,或TSD)。





回頁首


創(chuàng)建和注銷

Posix定義了兩個API分別用來創(chuàng)建和注銷TSD:

int pthread_key_create(pthread_key_t *key, void (*destr_function) (void *))

該函數從TSD池中分配一項,將其值賦給key供以后訪問使用。如果destr_function不為空,在線程退出(pthread_exit())時將以key所關聯的數據為參數調用destr_function(),以釋放分配的緩沖區(qū)。

不論哪個線程調用pthread_key_create(),所創(chuàng)建的key都是所有線程可訪問的,但各個線程可根據自己的需要往key中填入不同的值,這就相當于提供了一個同名而不同值的全局變量。在LinuxThreads的實現中,TSD池用一個結構數組表示:

static struct pthread_key_struct pthread_keys[PTHREAD_KEYS_MAX] = { { 0, NULL } };

創(chuàng)建一個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 <stdio.h>
            #include <pthread.h>
            pthread_key_t   key;
            void echomsg(int t)
            {
            printf("destructor excuted in thread %d,param=%d\n",pthread_self(),t);
            }
            void * child1(void *arg)
            {
            int tid=pthread_self();
            printf("thread %d enter\n",tid);
            pthread_setspecific(key,(void *)tid);
            sleep(2);
            printf("thread %d returns %d\n",tid,pthread_getspecific(key));
            sleep(5);
            }
            void * child2(void *arg)
            {
            int tid=pthread_self();
            printf("thread %d enter\n",tid);
            pthread_setspecific(key,(void *)tid);
            sleep(1);
            printf("thread %d returns %d\n",tid,pthread_getspecific(key));
            sleep(5);
            }
            int main(void)
            {
            int tid1,tid2;
            printf("hello\n");
            pthread_key_create(&key,echomsg);
            pthread_create(&tid1,NULL,child1,NULL);
            pthread_create(&tid2,NULL,child2,NULL);
            sleep(10);
            pthread_key_delete(key);
            printf("main thread exit\n");
            return 0;
            }

給例程創(chuàng)建兩個線程分別設置同一個線程私有數據為自己的線程ID,為了檢驗其私有性,程序錯開了兩個線程私有數據的寫入和讀出的時間,從程序運行結果可以看出,兩個線程對TSD的修改互不干擾。同時,當線程退出時,清理函數會自動執(zhí)行,參數為tid。

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發(fā)現有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多