线程特定数据TSD总结

一、线程的本质

Linux线程又称轻量进程(LWP),也就说线程本质是用进程之间共享用户空间模拟实现的。

二、线程模型的引入

线程模型引入是为了数据共享,为什么又引入线程私有数据?有时候想让基于进程的接口适应多线程环境,这时候就需要为每个线程维护一份私有数据了,最典型的就是errno了。

在维护每个线程的私有数据的时候,我们可能会想到分配一个保存线程数据的数组,用线程的ID作为数组的索引来实现访问。
1. 系统生成的线程ID不能保证是一个小而连续的整数
2. 用数组实现的时候容易出现越界读写的情况
鉴于这两个问题,我们可以借助线程的私有数据(TSD)来解决这个问题。

三、线程特定数据

线程私有数据(Thread Specific Data),是存储和查询与某个线程相关的数据的一种机制。把这种数据称为线程私有数据或线程特定数据的原因是,希望每个线程可以独立地访问数据副本,从而不需要考虑多线程同步问题。

提示:进程中的所有线程都可以访问进程的整个地址空间。除了使用寄存器以外(一个线程真正拥有的唯一私有存储是处理器的寄存器),线程没有办法阻止其他线程访问它的数据,线程私有数据也不例外。虽然底层的实现部分并不能阻止这种访问能力,但管理线程私有数据的函数可以提高线程间的数据独立性。

四、关键函数说明

  • int pthread_key_create(pthread_key_t *keyp,void (*destructor)(void *));
    返回值:若成功则返回0,否则返回错误编号
    功能:创建的键存放在keyp指向的内存单元,这个键可以被进程中的所有线程使用,但每个线程把这个键与不同的线程私有数据地址进行关联。
    说明:

    1. 创建一个线程私有数据键,必须保证对于每个Pthread_key_t变量仅仅被调用一次,因为如果一个键被创建两次,其实是在创建两个不同的键。第二个键将覆盖第一个键,第一个键以及任何线程可能与其关联的线程私有数据值将丢失。解决这种竞争的办法是使用pthread_once

      pthread_once_t initflag = PTHREAD_ONCE_INIT;
      int pthread_once(pthread_once_t *initflag, void (*initfn)(void));
      返回值:若成功则返回0,否则返回错误编号
      说明:initflag必须是一个非本地变量(即全局变量或静态变量),而且必须初始化为PTHREAD_ONCE_INIT。

    2. 当线程调用pthread_exit或者线程执行返回,正常退出时,如果私有数据不为空且注册了析构函数,析构函数就会被调用,但如果线程调用了exit_exit_Exitabort或出现其他非正常的退出时就不会调用析构函数注1

    3. 线程可以为线程私有数据分配多个键注2,每个键都可以有一个析构函数与它关联。各个键的析构函数可以互不相同,当然它们也可以使用相同的析构函数。
    4. 线程退出时,线程私有数据的析构函数将按照操作系统实现中定义的顺序被调用。析构函数可能会调用另一个函数,该函数可能会创建新的线程私有数据而且把这个数据与当前的键关联起来。当所有的析构函数都调用完成以后,系统会检查是否还有非null的线程私有数据值与键关联,如果有的话,再次调用析构函数。这个过程会一直重复直到线程所有的键都为null值线程私有数据,或者已经做了最大次数的尝试注3
    5. 创建新
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值