談談多線程編程的個人理解(數據私有變量)

 

1、儘管加了頭文件pthread.h,但多線程庫不在系統庫了,故需要手動添加參數,即-lpthread把庫libpthread.a加進去編譯。

2、線程私有數據
利用pthread_key_create(pthread_key *key, void (*destr_function)(void *))創建線程私有數據,即對各個線程都可見。其原理如下:
POSIX線程庫維護TSD池,具體爲一個結構數組,即
static struct pthread_key_struct pthread_keys[PTHREAD_KEYS_MAX]={{0, NULL}};
pthread_key_struct結構體中有兩項:int in_use或0;destructor函數
當利用函數創建一個線程私有數據時,該函數在TSD池中分配一項,也就是將該結構數組中的某一項的成員一設置爲in_use,設置destructor函數爲destr_function。並吧該數組的索引值返回給*key,這樣通過*key便可以查找該數組並做後繼的刪除TSD處理,還有線程結束時調用釋放函數。
各個線程都有一個二維數組,位於線程描述結構裏。用來存放與key關聯的值。
#define PTHREAD_KEY_2NDLEVEL_SIZE 32
#define PTHREAD_KEY_1STLEVEL_SIZE \
((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1)/PTHREAD_KEY_2NDLEVEL_SIZE)
這樣,跟某個key關聯的值會存放到稀疏矩陣中某個特定的位置。位置由如下公式決定:
idx1st = key/PTHREAD_KEY_2NDLEVEL_SIZE
idx2nd = key%PTHREAD_KEY_2NDLEVEL_SIZE
讀取某個跟key關聯的值也是利用此公式找到索引位置,然後讀出數據。
這樣,對於同一個線程來說,不同的線程私有數據,對應TDS池中不同的項,也就是結構數組中不同的項,也就是對應不同的結構數組索引值(存放於key中)。而與不同key關聯的值也會存放於該線程描述結構裏的二維數組的不同位置。一個key對應一個固定位置。而對於不同線程來說,雖然key值相同,都對應於結構數組的某一項,但與key關聯的值讀寫是對線程各自線程描述結構裏的二維數組相應位置進行讀寫,所以相互互不干擾。
由此可以看出,線程私有數據key對各個線程來說是可見的,但各個線程對其讀寫是互不干擾的。
當註銷線程私有數據時,線程私有數據註銷函數並不檢查是否有線程正在使用這個TSD,也不會調用清理函數,而只是釋放TSD以供下一次調用線程私有數據註冊函數時使用,具體爲把結構數組裏的某一項的成員設置爲0和NULL。
當線程結束時,會在線程資源(如線程描述結構)被回收前決定是否調用釋放函數。如果該線程私有數據有關聯值,則會以線程私有數據爲參數調用該釋放函數(實際是線程私有數據關聯值)。如果沒有關聯值則不會調用釋放函數。

註銷線程私有數據int pthread_key_delete(pthread_key_t key)
訪問TSD讀寫函數:
int pthread_setspecific(pthread_key_t key, const void *pointer)
void *pthread_getspecific(pthread_key_t key)

例程:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
pthread_key_t key;

void echomsg(void *t)
{
 printf("destructor excuted in thread %d, param=%d\n", pthread_self(), *(int *)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)
{
 pthread_t 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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章