谈谈多线程编程的个人理解(数据私有变量)

 

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;
}

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