linux线程特定数据,linux特定线程数据(TSD)

C 程序有两类基本数据:局部数据和全局数据。

对于多线程 C 程序,添加了第三类数据:线程特定数据。线程特定数据与全局数据非常相似,区别在于前者为线程专有。

线程特定数据基于每线程进行维护。TSD(特定于线程的数据)是定义和引用线程专用数据的唯一方法。每个线程特定数据项都与一个作用于进程内所有线程的键关联。通过使用 key,线程可以访问基于每线程进行维护的指针

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

pthread_key_t key;

int ret;

/* key create without destructor */

ret = pthread_key_create(&key, NULL);

/* key create with destructor */

ret = pthread_key_create(&key, destructor);

可以使用 pthread_key_create函数分配用于标识进程中线程特定数据的键。键对进程中的所有线程来说是全局的。创建线程特定数据时,所有线程最初都具有与该键关联的 NULL 值。

创建键之后,每个线程都会将一个值绑定到该键。这些值特定于线程并且针对每个线程单独维护。如果创建该键时指定了 destructor 函数,则该线程终止时,系统会解除针对每线程的绑定。

使用可选的析构函数 destructor 可以释放过时的存储。如果某个键具有非 NULL destructor 函数,而线程具有一个与该键关联的非 NULL 值,则该线程退出时,系统将使用当前的相关值调用 destructor 函数。destructor 函数的调用顺序不确定。

pthread_key_create 返回值pthread_key_create() 在成功完成之后返回零。其他任何返回值都表示出现了错误。如果出现以下任一情况,pthread_key_create() 将失败并返回相应的值。

EAGAIN

描述:key 名称空间已经用完。

ENOMEM

描述:此进程中虚拟内存不足,无法创建新键。

删除线程特定数据键使用 pthread_key_delete函数 可以销毁现有线程特定数据键。由于键已经无效,因此将释放与该键关联的所有内存。引用无效键将返回错误。

语法int pthread_key_delete(pthread_key_t key);

#include pthread_key_t key;

int ret;

/* key previously created */

ret = pthread_key_delete(key);

如果已删除键,则使用调用 pthread_setspecific() 或 pthread_getspecific() 引用该键时,生成的结果将是不确定的。

程序员在调用删除函数之前必须释放所有线程特定资源。删除函数不会调用任何析构函数。反复调用 pthread_key_create() 和 pthread_key_delete() 可能会产生问题。

对于每个所需的键,应当只调用 pthread_key_create() 一次。

pthread_key_delete() 在成功完成之后返回零。其他任何返回值都表示出现了错误。如果出现以下情况,pthread_key_delete() 将失败并返回相应的值。

EINVAL

描述:key 的值无效。

设置线程特定数据使用 pthread_setspecific() 可以为指定线程特定数据键设置线程特定绑定。

语法

int pthread_setspecific(pthread_key_t key, const void *value);

#include pthread_key_t key;

void *value;

int ret;

/* key previously created */

ret = pthread_setspecific(key, value);

返回值pthread_setspecific() 在成功完成之后返回零。其他任何返回值都表示出现了错误。如果出现以下任一情况,pthread_setspecific() 将失败并返回相应的值。

ENOMEM

描述:虚拟内存不足。

EINVAL

描述:key 无效。

注意:设置新绑定时,pthread_setspecific() 不会释放其存储空间。必须释放现有绑定,否则会出现内存泄漏。

获取线程特定数据请使用 pthread_getspecific 获取调用线程的键绑定,并将该绑定存储在 value 指向的位置中。

语法 void *pthread_getspecific(pthread_key_t key);

#include pthread_key_t key;

void *value;

/* key previously created */

value = pthread_getspecific(key);

返回值pthread_getspecific 不返回任何错误。

示例

#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 createkey(void)

{

pthread_key_create(&key,destructor);  //创建键.

}

void* threadFun1(void* arg)

{

static pthread_once_t once = PTHREAD_ONCE_INIT;

pthread_once(&once,createkey);   //为了只创建一次这个键.第一次调用pthread_once时它执行这个函数creatkey,以后的调用将忽略

char* p = (char*)malloc(LEN);

printf("%x\n",p);

pthread_setspecific(key,p);

//sleep(2);

A("Thread1");

B();

}

void* threadFun2(void* arg)

{

static pthread_once_t once = PTHREAD_ONCE_INIT;

pthread_once(&once,createkey);

char* p = (char*)malloc(LEN);

printf("%x\n",p);

pthread_setspecific(key,p);

//  A("Thread1");

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");

//  B();

pthread_join(tid1,NULL);

pthread_join(tid2,NULL);

return 1;

}

注意:当用pthread_setspecific为一个键指定新的特定线程数据时,必须自己释放原有的特定线程数据以回收空间. pthread_key_delete用来删除一个键,这个键占用的内存将释放,但它只释放键占用的内存,并不释放键关联的特定线程数据所占用的内存资源,而且它也不会触发函数pthread_key_create中注册的destructor函数.特定线程数据的释放必须在释放键之前完成.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值