有关线程局部存储

首先看一下百科上面的解释:

英文为Thread Local Storage,缩写为TLS。为什么要有TLS?原因在于,全局变量与函数内定义的静态变量,是各个线程都可以访问的共享变量。
在一个线程修改的内存内容,对所有线程都生效。这是一个优点也是一个缺点。说它是优点,线程的数据交换变得非常快捷。说它是缺点,一个线程死掉了,其它线程也性命不保; 多个线程访问共享数据,需要昂贵的同步开销,也容易造成同步相关的BUG。
如果需要在一个线程内部的各个函数调用都能访问、但其它线程不能访问的变量(被称为static memory local to a thread 线程局部静态变量),就需要新的机制来实现。这就是TLS。
线程局部存储在不同的平台有不同的实现,可移植性不太好。幸好要实现线程局部存储并不难,最简单的办法就是建立一个全局表,通过当前线程ID去查询相应的数据,因为各个线程的ID不同,查到的数据自然也不同了。但Windows系统采用了每个线程建线程专享的索引表,表的条目为线程局部存储的地址。在线程执行的任何代码处,都可以查询本线程的这个索引表获得要访问的线程局部存储的地址。
大多数平台都提供了线程局部存储的方法,无需要我们自己去实现

这里看一下Linux是怎么实现的。

linux实现
  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);

下面说一下线程存储的具体用法。
1) 创建一个类型为 pthread_key_t 类型的变量。
2)调用 pthread_key_create() 来创建该变量。该函数有两个参数,第一个参数就是上面声明的 pthread_key_t 变量,
第二个参数是一个清理函数,用来在线程释放该线程存储的时候被调用。该函数指针可以设成 NULL ,这样系统将调用默认的清理函数。
3)当线程中需要存储特殊值的时候,可以调用 pthread_setspcific() 。该函数有两个参数,第一个为前面声明的 pthread_key_t 变量,
第二个为 void* 变量,这样你可以存储任何类型的值。
4) 如果需要取出所存储的值,调用 pthread_getspecific() 。该函数的参数为前面提到的 pthread_key_t 变量,该函数返回
void * 类型的值。

实例:

#include <malloc.h>
#include <pthread.h>
#include <stdio.h>

static pthread_key_t thread_log_key;
void close_thread_log (void* thread_log)
{
	
}
pthread_mutex_t smc_threadMutex;
void* thread_function (void* args)
{
	char thread_log_filename[20];
	FILE* thread_log;
	int threadId = 0;
	int temp = 0;
	int *threadId_2 = temp;
	threadId = pthread_self();
	pthread_mutex_lock(&smc_threadMutex); //加锁,否则打印出来的结果可能次序不对
	printf("my threadId is %d.\n", threadId);
	pthread_setspecific (thread_log_key, threadId);
	threadId_2 = (int*)pthread_getspecific (thread_log_key);
	printf("my threadId_2 is %d.\n", *threadId_2);
	pthread_mutex_unlock(&smc_threadMutex);
	sleep(2);
//	write_to_thread_log ("Thread starting.");
	/* Do work here... */
	return NULL;
}

int main ()
{
	int i;
	pthread_t threads[5];
	/* Create a key to associate thread log file pointers in
	thread-specific data. Use close_thread_log to clean up the file
	pointers. */
	pthread_mutex_init(&smc_threadMutex, NULL);
	pthread_key_create (&thread_log_key, close_thread_log);
	/* Create threads to do the work. */
	for (i = 0; i < 5; ++i)
	pthread_create (&(threads[i]), NULL, thread_function, NULL);
	/* Wait for all threads to finish. */
	for (i = 0; i < 5; ++i)
	pthread_join (threads[i], NULL);
	return 0;
}  

使用gcc pthread_key.c  -lpthread

运行结果:

root@leaves-desktop:/home/leaves/android/temp# ./a.out
my threadId is -1249662144.
my threadId_2 is -1249662144.
my threadId is -1241269440.
my threadId_2 is -1241269440.
my threadId is -1232876736.
my threadId_2 is -1232876736.
my threadId is -1224484032.
my threadId_2 is -1224484032.
my threadId is -1216091328.
my threadId_2 is -1216091328.
root@leaves-desktop:/home/leaves/android/temp# 



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值