TLS--线程本地存储
前言
线程局部存储(TLS),是一种变量的存储方法,这个变量在它所在的线程内是全局可访问的,但是不能被其他线程访问到,这样就保持了数据的线程独立性。
一、Windows下的TLS
1.静态的TLS
_declspec(thread) Object data=0;
原理
:x86系统下,申请的静态TLS都有三个机器指令。如果新建一个线程,会自动捕捉三个指令并把它分配一个内存块,用来存放该静态TLS变量,新线程拥有它自己TCL的访问权,不能访问其他线程的
2.动态的TLS
TlsAlloc函数 分配数组索引
TlsAlloc成功返回索引,失败返回TLS_OUT_OF_INDEXES
DWORD WINAPI TlsAlloc(void);
TlsSetValue函数 设置变量值
当一个线程调用TlsSetValue函数成功时,他会修改自己的PVOID数组,但它无法修改另一个线程TLS值。(只修改自己的)
BOOL WINAPI TlsSetValue(
DWORD dwTlsIndex, //索引值,表示在数组中的具体位置
LPVOID lpTlsValue //要设置的值
);
TlsGetValue函数获取变量值
返回在索引为dwTlsIndex 的TLS元素中保存的值,TlsGetValue只会查看属于调用线程的数组。(只能查看自己的)
LPVOID WINAPI TlsGetValue(
DWORD dwTlsIndex //索引值,表示在数组中的具体位置
);
TlsFree函数 释放索引
BOOL
WINAPI
TlsFree(
DWORD dwTlsIndex //标记的索引值
)
二.Linux下的TLS
注意
:只能修饰POD类型(带自定义的构造、拷贝、赋值、析构的类型,不带深拷贝的)
当一个线程终止时,任何该线程中的线程局部存储变量都不再有效
不能修饰class类型,因为无法自动调用构造函数和析构函数,可以用于修饰全局变量,函数内的静态变量
不能修饰函数的局部变量或者class的普通成员变量
声明
:
__thread int i;
extern __thread struct state s;
static __thread char *p;
#include<iostream>
#include<pthread.h>
#include<unistd.h>
using namespace std;
__thread int var=10;
void* text1(void* arg){
var+=5;
cout<<var<<endl;//输出 15
}
void* text2(void* arg){
var+=1;
sleep(1);
cout<<var<<endl;//输出6
}
int main(){
pthread_t pid1,pid2;
static __thread int temp=10;//修饰函数内的static变量
pthread_create(&pid1,NULL,text1,NULL);
pthread_create(&pid2,NULL,text2,NULL);
pthread_join(pid1,NULL);
pthread_join(pid2,NULL);
//__thread int temp=5; //错误的
cout<<temp<<endl;//输出10
return 0;
}