Chinaunix首页 | 论坛 | 博客
  • 博客访问: 410074
  • 博文数量: 82
  • 博客积分: 2600
  • 博客等级: 少校
  • 技术积分: 961
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-08 21:44
文章分类
文章存档

2013年(2)

2012年(56)

2010年(24)

我的朋友

分类: C/C++

2010-06-03 00:07:39

该文原作者不详

POSIX要求实现POSIX的系统为每个进程维护一个称之为Key的结构数组,这个数组中的每一个结构称之为一个线程特定数据元素。POSIX规定系统实现的Key结构数组必须包含不少于128个线程特定数据元素,而每个线程特定数据元素中至少包含两项内容,使用标记和析构函数指针。线程特定数据元素中的使用标志指示这个数组元素是否正在使用,初始值为'不在使用';我们稍后讨论线程特定数据元素中的析构函数指针。在后面的介绍中个,我们假设Key结构数组中包含128个元素。

key结构数组中每个元素的索引(0~127)称之为键(Key),当一个线程调用pthread_key_create创建一个新的线程特定数据元素时,系统搜索所在进程的Key结构数组,找出其中第一个不再使用的元素,并返回该元素的键。

除了Key结构数组,系统还在进程中维护关于每个线程的多种信息。这些特定的线程的信息别保存在称之为pthread机构中,pthread结构中包含名为pkey的指针数组,其长度为128,初始值为空,这128个指针与Key结构数组的128个线程特定数据元素一一对应。在调用pthread_key_create得到一个键之后,每个线程可以依据这个键操作自己的pkey指针数组中对应的指针,这通过pthread_getspecific和pthread_setpecific函数来实现的。

我们使用线程特定数据机制,就是要使线程中的函数可以共享一些数据。如果我们在线程中通过malloc获取一块内存,并把该内存的指针通过pthread_setspecific设置到pkey指针数组中对应的Key的位置,那么线程中调用的函数即可通过pthread_getspecific获得这个指针,这就实现了线程内部数据在各个函数间的共享。当一个线程终止时,系统将扫描该线程的pkey数组,为每个非空的Pkey指针调用对应的析构函数,因此只要将执行回收的函数指针在调用pthread_key_create时作为函数的参数,即可在线程终止时自动回收分配的内存区。

下面可以通过实例来理解线程特定数据的机制

#include
#include
#include


#define LEN 100
pthread_key_t key;

void A(char* s)
{
char* p = (char*)pthread_getspecific(key);
strcpy(p,s);
}

void B()
{
char* p = (char*)pthread_getspecific(key);
printf("%s\n",p);
}

void destructor(void* ptr)
{
// sleep(1);
printf("...%x\n",(char*)ptr);
free(ptr);
printf("Memorey free\n");
}

void* threadFun1(void* arg)
{
char* p = (char*)malloc(LEN);
printf("%x\n",p);
pthread_setspecific(key,p);
//sleep(2);
A("Thread1");
B();
}

void* threadFun2(void* arg)
{

char* p = (char*)malloc(LEN);
printf("%x\n",p);
pthread_setspecific(key,p);
A("Thread2...");
B();

}

int main()
{
pthread_t tid1,tid2;
pthread_key_create(&key,destructor);
if(pthread_create(&tid1, NULL, &threadFun1, NULL) != 0)
   printf("create thread1 fail\n");

if(pthread_create(&tid2, NULL, &threadFun2, NULL) != 0)
   printf("create thread2 fail\n");

pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
return 1;
}

在这个程序中,函数A和函数B共享了一个内存区,而这个内存区是特定于调用A和B的线程,对于其它线程,这个内存区时不可见的,这就安全有效的达到了在线程中的各个函数之间共享数据的目的。

阅读(1930) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-09-04 23:23:58

这个需要认真的看和理解!