Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1472119
  • 博文数量: 254
  • 博客积分: 8696
  • 博客等级: 中将
  • 技术积分: 2961
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-03 16:46
文章分类

全部博文(254)

文章存档

2015年(4)

2014年(18)

2013年(16)

2012年(8)

2011年(25)

2010年(2)

2009年(74)

2008年(107)

分类: LINUX

2014-03-12 18:03:31

一个标准的线程由 线程ID 当前指令指针(PC) 寄存器集合 和 堆栈组成

见--码农自我修养 线程部分
1.为什么需要线程私有数据:
原 因一:有时候需要维护基于每个线程的数据,用线程ID作为索引。因为线程ID不能保证是小而连续的整数,所以不能简单的分配一个线程数据数组,用线程ID 作为数组的索引。即使线程ID确实是小而连续的整数,可能还希望有一些额外的保护,以防止某个线程的数据和其它线程的数据相混淆。
原因二:可以让基于进程的接口适应多线程环境,比如errno,线程出现以前errno被定义成进程环境中全局可访问的整数,线程出现以后,为了让线程也能使用那些原本基于进程的系统调用和库例程,errno被重新定义成线程私有数据。
(参考APUE2)
2.进程中的所有线程都可以访问进程的整个地址空间,除非使用寄存器(一个线程真正拥有的唯一私有存储是处理器寄存器),线程没有办法阻止其它线程访问它的数据,线程私有数据也不例外,但是管理线程私有数据的函数可以提高线程间的数据独立性。

3.int pthread_key_create(pthread_key_t *keyp, void (*destructor)(void *));
在分配(malloc)线程私有数据之前,需要创建和线程私有数据相关联的键(key),这个键的功能是获得对线程私有数据的访问权。
如 果创建一个线程私有数据键,必须保证Pthread_key_create对于每个Pthread_key_t变量仅仅被调用一次,因为如果一个键被创建 两次,其实是在创建两个不同的键,第二个键将覆盖第一个键,第一个键以及任何线程可能为其关联的线程私有数据值将丢失。
创建新键时,每个线程的数据地址设为NULL。


4.关于析构函数void (*destructor)(void *):
当线程退出时,如果线程私有数据地址被置为非NULL值,那么析构函数就会被调用。
当线程调用pthread_exit或者线程执行返回,正常退出时,析构函数就会被调用,但是如果线程调用了exit系列函数或者abort或者其它非正常退出时,就不会调用析构函数。

5. 线程退出时,线程私有数据的析构函数将按照OS实现定义的顺序被调用。析构函数可能调用另外一个函数,而该函数可能创建新的线程私有数据而且把这个线程私 有数据和当前的键关联起来。当所有的析构函数都调用完成以后,系统会检查是否有非NULL的线程私有数据值与键关联,如果有的话,再次调用析构函数,这个 过程一直重复到线程所有的键都为NULL值线程私有数据,或者已经做了PTHREAD_DESTRUCTOR_ITERATIONS中定义的最大次数的尝 试.

当下爱你成退出时,Pthreads在进程汇总检查所有的线程私有数据键,并且将不是NULL的线程私有数据简置NULL,然后调用键的destructor函数。

6.int pthread_delete(pthread_key_t *keyp),注意调用pthread_delete不会激活与键关联的析构函数,容易造成内存泄露。
当删除线程私有数据键的时候,不会影响任何线程对该键设置的线程私有数据值,甚至不影响调用线程当前键值,所以容易造成内存泄露,如果你不记得释放所有线程内与该键相关联的私有数据空间的话。
使用已经删除的私有数据键将导致未定义的行为。

编程建议:最后不删除线程私有数据键!!!尤其当一些线程仍然持有该键的值时,就更不该释放该键!!!

7.需要确保分配的键不会由于初始化阶段的竞争而发生变动。(使用pthread_once避免)
容易发生竞争的代码段:
void destructor(void *);

pthread_key_t key;
int      flag;

int threadfun(void *arg)
{
if(!flag){
       flag = 1;
       pthread_key_create(&key, destructor);
    }
}


使用pthread_once:
void destructor(void *);

pthread_once_t initonce = PTHREAD_ONCE_INIT;
pthread_key_t  key;

void thread_once(void)
{
pthread_key_create(&key, destructor);
}

int threadfun(void *arg)
{
pthread_once(&initonce, thread_once);
...
}

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

if(pthread_getspecific(key) == NULL){
    printf("需要调用pthread_setspecific");
}

原文:http://blog.csdn.net/tedious/article/details/7776897
阅读(910) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~