加载中…
正文 字体大小:

线程局部存储(TLS)

(2014-02-12 13:06:07)
标签:

变量

数据

两种

情况

自然

分类: C语言

    同一个进程中的多个线程,它们的内存空间是共享的(栈除外),一个线程对内存的修改,对所有的线程都有效。这既是一个优点也是一个缺点。说它是优点,因为这样会让线程间的数据交换快捷高效。说它是缺点,一个线程死掉了,其他线程也将性命不保。

   采用线程局部存储,每个线程有一定的私有空间。这可以避免部分无意的破坏(当然无非避免有意的破坏行为),也省去线程访问共享数据时出现的问题。

    在有的情况下,没有线程局部存储,确实很难用其他办法实现。比如,glibc会把最后一次操作的错误码记录在errno变量里,如果不采用线程局部存储,在多线程的情况下,当前线程取得errno可能不是自己上一次操作的错误码。

    线程局部存储在不同的平台上有不同的实现,可移植性不太好。幸好要实现线程局部存储并不难,最简单的办法就是建立一个全局表,通过当前线程ID去查询相应的数据,因为各个线程的ID不同,查到的数据自然也不同了。

    大多数平台都提供了线程局部存储的方法,无需要我们自己去实现,在Linux下有两种方法可以实现线程局部存储。

方法一:使用pthread的函数

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

int pthread_key_delete(pthread_key_t key);

void *pthread_getspecific(pthread_key_t key);

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

示例如下。

static pthread_key_t key;

static pthread_once_t key_once = PTHREAD_ONCE_INIT;

 

static void make_key(void)

{

    pthread_key_create(&key, NULL);

    return ;

}

 

void* thread_entry(void* param)

{

    pthread_once(&key_once, make_key);

    if (pthread_getspecific(key) == NULL)

    {

         pthread_setspecific(key, (void*)pthread_self());

    }

    printf("data=%u\n", pthread_getspecific(key));

    return NULL;

}

pthread_once保证make_key只被执行一次。

 

方法二:使用编译器扩展

示例如下:

__thread int i;

    方法二使用起来方便很多,但前者的好处是移植比较方便,即使编译器本身不支持,也可以自己封装相应的函数。

0

阅读 评论 收藏 转载 喜欢 打印举报
后一篇:内存
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

    后一篇 >内存
      

    新浪BLOG意见反馈留言板 电话:4006900000 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有