线程私有数据

线程私有数据的作用?

线程私有数据的实现?


一 概述:

(1)线程存储器模型:(深入理解计算机系统)

*一组并发线程运行在一个进程的上下文中,每个线程都有自己独立的线程上下文:线程ID、栈、栈指针、程序计数器、条件码和通用目的的寄存器值。每个线程和和其它线程共享进程上下文的剩余部分:整个用户虚拟地址空间(代码、读/写数据、堆、已经所有共享库代码和数据区),也共享同样的打开文件集合。


(2)线程私有数据(Thread-specific data,TSD):存储和查询与某个线程相关数据的一种机制。

*在进程内的所有线程都共享相同的地址空间,即意味着任何声明为静态或外部变量,或在进程堆声明的变量,都可以被进程内所有的线程读写。

*一个线程真正拥有的唯一私有存储是处理器寄存器,栈在“主人”故意暴露给其他线程时也是共享的。

*有时需要提供线程私有数据:可以跨多个函数访问(全局);仅在某个线程有效(私有)。例如:errno。


(3)linux TSD池:(参看源代码)

*不论哪个线程调用pthread_key_create(),所创建的key都是所有线程可访问的,但各个线程可根据自己的需要往key中填入不同的值,这就相当于提供了一个同名而不同值的全局变量。

*在LinuxThreads的实现中,TSD池用一个结构数组表示:

static struct pthread_key_struct pthread_keys[PTHREAD_KEYS_MAX] = { { 0, NULL } };

创建一个TSD就相当于将结构数组中的某一项设置为“in_use”,并将其索引返回给*key,然后设置destructor函数 destr_function。

(4)线程可以线程的私有数据分配多个键,每个键都可以有一个析构函数与它关联。


二 相关函数:

*在分配线程私有数据之前,需要创建与该数据关联的。这个键用于获取对线程私有数据的访问权。


(1)pthread_key_create(pthread_key_t *key,void (*destructor)(void *)):创建一个键。

*key:创建的存放在key指向的内存单元,这个键可以被进程中所有线程使用,但每个线程把这个键与不同的线程私有数据地址进行关联。创建新键时,每个线程的数据地址设为null值。

*destructor:pthread_key_create可以选择为该键关联析构函数。如果destructor参数为null,就说明没有析构函数与键关联。线程退出时,如果其数据地址为非null数值,那么析构函数就会被调用。线程正常退出(pthread_exit或线程执行返回),析构函数会被调用;如果线程调用exit、_exit、_Exit、abort或出现其他非正常退出时,就不会调用析构函数。如果你的线程私有数据地址为堆存储的地址,并且你想要再destructor函数中释放存储,就必须传递给destructor参数,而非调用pthread_getspecific的参数。(详细参考posix多线程程序设计)

*对于每个pthread_key_t变量(即键)必须仅调用一次pthread_key_create。如果一个键创建两次,其实是在创建不同的键,第二个键将覆盖第一个,第一个键与任何线程可能为其设置的值将一起永远的丢失。所以,pthread_key_create放在主函数中执行;或每个线程使用pthread_once来创建键。


(2)一次初始化:一些事情仅仅需要做一次。

pthread_once_t initflag=PTHREAD_ONCE_INIT

pthread_once(pthread_once_t *initflag,void (*initfn)(void))

*initflag必须是一个非局部变量(即全局变量或静态变量),必须初始化为PTHREAD_ONCE_INIT。

*initfn:初始化函数。

*使用pthread_once创建键的格式:

pthread_key_t key;

pthread_once_t initflag=PTHREAD_ONCE_INIT;

void thread_init()

{pthread_key_create(key,destructor);}

int threadfunc()

{

pthread_once(initflag,thread_init);

}


(3)pthread_key_delete(pthread_key_t *key)

*对所有线程都可以调用pthread_key_delete来取消键与线程私有数据之间的关联关系。

*注意:调用pthread_key_delete不激活与该键关联的析构函数。

*POSIX保证一次只能有128个线程私有数据键,因此释放你不再需要的键是有用的。实际支持的键数目由PTHREAD_KEYS_MAX标志的值指定。


(4)关联键和线程私有数据:pthread_setspecific(pthread_key_t key,const void *value);

获取线程私有数据地址:pthread_getspecific(pthread_key_t key);

*如果没有关联私有数据,pthread_getspecific将返回一个空指针,可以据此来判断是否需要调用pthread_setspecific。

*使用pthread_setspecific将线程私有数据键设为NULL,这不是在赋空值,而是说该键在当前的线程中不再有值。





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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值