posts - 134,comments - 22,trackbacks - 0
           在多線程環境下,進程內的所有線程共享進程的數據空間,因此全局變量為所有線程共有。在程序設計中有時需要保存線程自己的全局變量,這種特殊的變量僅在某個線程內部有效。如常見的變量errno,它返回標準的出錯代碼。errno不應該是一個局部變量,幾乎每個函數都應該可以訪問它;但它又不能作為一個全局變量,否則在一個線程里輸出的很可能是另一個線程的出錯信息,這個問題可以通過創建線程的私有數據(Thread-specific Data,或TSD)來解決。在線程內部,線程私有數據可以被各個函數訪問,但它對其他線程是屏蔽的。
              線程私有數據采用了一種被稱為一鍵多值的技術,即一個鍵對應多個數值。訪問數據時都是通過鍵值來訪問,好像是對一個變量進行訪問,其實是在訪問不同的數據。使用線程私有數據時,首先要為每個線程數據創建一個相關聯的鍵。在各個線程內部,都使用這個公用的鍵來指代線程數據,但是在不同的線程中,這個鍵代表的數據是不同的。操作線程私有數據的函數主要有4個:pthread_key_create(創建一個鍵),pthread_setspecific(為一個鍵設置線程私有數據),pthread_getspecific(從一個鍵讀取線程私有數據),pthread_key_delete(刪除一個鍵)。這幾個函數的聲明如下:
          #include <pthread.h>
          int pthread_key_create(pthread_key_t *key,void (*destr_function)(void *));
          int pthread_setspecific(pthread_key_t key,const void *pointer));
          void *pthread_getspecific(pthread_key_t key);
          int pthread_key_delete(pthread_key_t key);
              pthread_key_create:從Linux的TSD池中分配一項,將其值賦給key供以后訪問使用,它的第一個參數key為指向鍵值的指針,第二個參數為一個函數指針,如果指針不為空,則在線程退出時將以key所關聯的數據為參數調用destr_function(),釋放分配的緩沖區。
              key一旦被創建,所有線程都可以訪問它,但各線程可以根據自己的需要往key中填入不同的值,這就相當于提供了一個同名而不同值的全局變量,一鍵多值。一鍵多值靠的是一個關鍵數據結構數組,即TSD池其結構如下:
          static struct pthread_key_struct pthread_keys[PTHREAD_KEYS_MAX] ={{0,NULL}};
              創建一個TSD就相當于將結構數組中的某一項設置為“in_use”,并將其索引返回給*key,然后設置destructor函數destr_function。
              pthread_setspecific:該函數將pointer的值(不是內容)與key相關聯。用pthread_setspecific為一個鍵指定新的線程數據時,線程必須先釋放原有的線程數據用以回收空間。
              pthread_getspecific:通過該函數得到與key相關聯的數據。
              pthread_key_delete:該函數用來刪除一個鍵,鍵所占用的內存將被釋放。需要注意的是,鍵占用的內存被釋放,與該鍵關聯的線程數據所占用的內存并不被釋放。因此,線程數據的釋放必須在釋放鍵之前完成。
              例8-4將實現如何創建和使用線程的私有數據,具體代碼如下所示。
              例8-4
          #include <stdio.h>
          #include <string.h>
          #include <pthread.h>

          pthread_key_t key;

          void * thread2(void *arg)
          {
          int tsd = 5;
          printf("thread %d is running\n",pthread_self());
          pthread_setspecific(key,(void *)tsd);
          printf("thread %d returns %d\n",pthread_self(),pthread_getspecific(key));
          }

          void * thread1(void *arg)
          {
          int tsd = 0;
          pthread_t thid2;

          printf("thread %d is running\n",pthread_self());
          pthread_setspecific(key,(void *)tsd);
          pthread_create(&thid2,NULL,thread2,NULL);
          sleep(2);
          printf("thread %d return %d\n",pthread_self(),pthread_getspecific(key));
          }

          int main(void)
          {
          pthread_t thid1;
          printf("main thread begins running\n");
          pthread_key_create(&key,NULL);
          pthread_create(&thid1,NULL,thread1,NULL);
          sleep(5);
          pthread_key_delete(key);
          printf("main thread exit\n");
          return 0;
          }
              編譯并執行,結果如下:
          $ gcc -o 8-4 8-4.c -g -l pthread
          $ ./8-4
          main thread begins running
          thread -1209746544 is running
          thread -1218139248 is running
          thread -1218139248 returns 5
          thread -1209746544 return 0
          main thread exit
              程序說明:程序中,主線程創建了線程thread1,線程thread1創建了線程thread2。兩個線程分別將tsd作為線程私有數據。從程序運行結果可以看出,兩個線程tsd的修改互不干擾,可以看出thread2先于thread1結束,線程在創建thread2后,睡眠3s等待thread2執行完畢。主線程睡眠5s等待thread1結束。可以看出thread2對tsd的修改并沒影響到thread1的tsd的取值。
          posted on 2010-05-29 15:16 何克勤 閱讀(2411) 評論(0)  編輯  收藏 所屬分類: GNU Linux/UnixLinux 多線程
          主站蜘蛛池模板: 仙游县| 宝坻区| 莎车县| 武邑县| 特克斯县| 贵阳市| 喀喇沁旗| 广河县| 白城市| 西峡县| 泸西县| 盐源县| 共和县| 大英县| 蒙山县| 犍为县| 新野县| 塘沽区| 三江| 六枝特区| 太白县| 宜阳县| 呼伦贝尔市| 淮安市| 台东市| 蓬安县| 东宁县| 巴东县| 卢龙县| 汝阳县| 滦平县| 抚州市| 临高县| 启东市| 韶山市| 永新县| 云梦县| 黄石市| 河南省| 尉氏县| 芜湖县|