目录
是什么
线程的局部存储(Thread-Local Storage,TLS)是线程特定存储(Thread-Specific Storage,TSS)的更常用的名称,是一种内存区域,每个线程都可以存储自己的数据,使得不同的线程可以拥有不同的内存空间,相当于进程地址空间的全局变量区,只不过是线程私有的。线程局部存储在操作系统级别提供了一种方式,允许线程独立存储空间,为每个线程维护一份数据副本。这种特性在多线程编程中非常有用,因为它允许每个线程独立地存储自己的数据,避免了线程间的数据冲突和竞态条件。这使得编程更简单、更安全,并且减少了错误的可能性。
线程局部存储主要适用于需要高效处理大量并发线程的环境。它在很多高级语言中(如C++)也有实现,比如通过智能指针或者RAII(Resource Acquisition Is Initialization)来管理线程特定的数据。
实现方式:
-
Thread Local Storage (TLS) API:操作系统提供了TLS的API,可以让程序员创建和管理每个线程的局部存储变量。这些API通常由操作系统库或线程库提供,并可以在程序中直接使用。
-
编程语言支持:一些编程语言提供了内置的机制来支持线程的局部存储。例如,在Java中,可以使用ThreadLocal类来创建线程本地变量,每个线程都有其自己的副本;在C++中,可以使用thread_local关键字来声明线程局部存储变量。
-
动态链接库:有些动态链接库(DLL)或共享对象(SO)提供了自己的TLS支持,可以让程序员将数据关联到线程中。这种方式通常需要使用库提供的特定函数来设置和获取线程局部存储的值。
linux中声明线程局部存储变量
使用__thread
关键字
要声明一个线程局部存储变量,可以在变量声明前加上__thread
关键字,例如:
__thread int my_variable;
这将声明一个线程局部存储的整数变量my_variable
,每个线程都有自己的副本。在多线程环境中,不同线程可以访问和修改自己的副本,而不会影响其他线程的数据。
使用pthread_key_t
类型
声明一个线程局部存储的整数变量tls_key
pthread_key_t tls_key;
线程的局部存储具有以下特点:
-
线程隔离:每个线程都有它自己的局部存储空间,可以在该空间中存储线程特定的数据,不同线程之间的数据互相隔离,避免了数据冲突和竞态条件。
-
数据共享:线程的局部存储允许不同线程之间共享代码,而不是对整个进程进行数据共享。这样可以减少线程间的通信开销,提高并发性能。他的作用类似于在普通进程中的全局变量,进程中的所有函数都可以直接调用这个变量而不用传参导致麻烦。
-
线程安全:线程的局部存储可以提供一种线程安全的方式来处理数据,每个线程都可以独立地修改和访问自己的局部存储变量,不会对其他线程造成影响。
线程局部存储的限制
-
由于每个线程都有自己的存储空间,因此如果线程之间需要共享数据,那么就需要额外的机制来同步访问。
-
线程局部存储的空间通常有限制,尤其是在资源受限的环境中。因此,在使用线程局部存储时,需要仔细考虑数据的大小和数量,以确保线程之间的数据不会造成过多的内存占用。不能对自定义的类进行局部存储。
-
由于线程局部存储是基于操作系统的特性,因此它可能会受到操作系统实现的影响。不同的操作系统可能会有不同的线程局部存储实现和限制。
__thread:(使用简单,这里只给出例子)
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
// 声明线程局部存储变量
__thread int tls_variable;
// 线程函数
void* thread_func(void* arg) {
// 设置线程局部存储变量的值
tls_variable = pthread_self();
// 打印线程局部存储变量的值
printf("Thread local variable: %ld\n", tls_variable);
pthread_exit(NULL);
}
int main() {
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, thread_func, NULL);
pthread_create(&thread2, NULL, thread_func, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return 0;
}
在这个例子中,我们声明了一个线程局部存储变量tls_variable
,它在每个线程中都有自己的副本。在thread_func
线程函数中,我们将线程的ID(通过pthread_self()
函数获取)赋值给线程局部存储变量tls_variable
。然后,在每个线程中打印该变量的值。
在main
函数中,我们创建了两个线程,并等待它们结束。每个线程在运行过程中都具有自己的线程局部存储变量,并且变量的值不会被其他线程所修改。
线程特定键pthread_key_t
pthread_key_t
是 POSIX 线程库(pthreads)的一部分,它提供了一种机制,使得每个线程都可以拥有自己的数据,而这些数据不会被其他线程访问。这种机制在多线程程序中非常有用,因为它可以避免全局变量的竞争条件,同时也无需在每个线程中复制数据。
/* Keys for thread-specific data */ typedef unsigned int pthread_key_t;
在 Linux 系统中,pthread_key_t
是一个无符号整数类型,通常在 <pthread.h>
头文件中。你可以使用 pthread_key_create()
函数来创建一个新的线程特定键,使用 pthread_key_delete()
函数来销毁一个线程特定键。
pthread_key_create函数
pthread_key_