线程本地变量介绍

2022-10-21 language

在多线程程序中,所有线程共享程序中的变量,对于全局变量,所有线程都可以访问修改,如果希望么个线程单独使用,那么就需要 Thread Local Storage, TLS 了。

简言之,表面是一个全局变量,所有线程都可以使用它,而实际实现时,它的值在每一个线程中又是单独存储的。

示例

TSD 的使用方法简单介绍如下:

  • 声明一个类型为 pthread_key_t 类型的全局变量,后续所有的操作都会用到该变量;
  • 在创建线程前调用 pthread_key_create() 创建该变量,入参为上面的变量以及清理函数(为 NULL 时调用默认的清理函数);
  • 启动线程,在不同的线程中分别通过 pthread_setspcific()pthread_getspecific() 函数设置以及获取变量。

使用的函数声明如下。

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

如下是一个简单示例。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

pthread_key_t key;
struct test_struct { // 用于测试的结构
    int i;
    float k;
};

void *child1(void *arg)
{
	struct test_struct struct_data;
	struct_data.i = 10;
	struct_data.k = 3.1415;
	pthread_setspecific(key, &struct_data);
	printf("child1--> 0x%p\n", &(struct_data));
	printf("child1--> 0x%p\n", (struct test_struct *)pthread_getspecific(key));
	printf("child1--%d %f\n", ((struct test_struct *)pthread_getspecific(key))->i,
		((struct test_struct *)pthread_getspecific(key))->k);
}
void *child2(void *arg)
{
	int temp = 20;
	sleep(1);
	pthread_setspecific(key, &temp);
	printf("child2--> 0x%p\n", &temp);
	printf("child2--> 0x%p\n", (int *)pthread_getspecific(key));
	printf("child2--> %d\n", *((int *)pthread_getspecific(key)));
}

int main(void)
{
	int rc;
	pthread_t tid1, tid2;

	rc = pthread_key_create(&key, NULL);
	if (rc) {
		fprintf(stderr, "create thread key failed, %s.", strerror(rc));
		return -1;
	}

	pthread_create(&tid1, NULL, child1, NULL);
	pthread_create(&tid2, NULL, child2, NULL);
	pthread_join(tid1, NULL);
	pthread_join(tid2, NULL);

	pthread_key_delete(key);
	return (0);
}