线程局部存储
2018-08-18 本文已影响0人
ColdWave
线程局部存储
线程局部存储(TLS,thread local storage) 就是拥有线程生命周期及线程可见性的变量。
线程局部存储实际上是由单线程程序中的全局/静态变量被应用到多线程程序中被线程共享而来。我们可以简单地回顾一下所谓的线程模型。通常情况下,线程会拥有自己的栈空间,但是堆空间、静态数据区则是共享的。这样一来,全局、静态变量在这种多线程模型下总是再线程间共享的。
全局,静态变量的共享会带来好处,但是并不是所有的全局,静态变量适合在在多线程的情况下共享。
#include <pthread.h>
#include <iostream>
int errorCode = 0;
void* MaySetErr(void* input)
{
if (*(int *)input == 1)
errorCode = 1;
else if (*(int *)input == 2)
errorCode = -1;
else
errorCode = 0;
}
int main()
{
int input_a = 1;
int input_b = 2;
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, &MaySetErr, &input_a);
pthread_create(&thread2, NULL, &MaySetErr, &input_b);
pthread_join(thread2, NULL);
pthread_join(thread1, NULL);
std::cout << errorCode << std::endl;
return 0;
}
errorCode 值无法确定。因为 线程1 和 线程2 的执行顺序是无法确定的。
实际上,本例中 errorCode 即是 POSIX 标准中的错误全局变量 errno 在多线程情况下遇到问题的一个简化。
一旦 errno 在线程间共享时,则一些程序中允许的错误将会被隐藏不报。而解决方法就是为每个线程指派一个全局的 errno,即 TLS 化 的 errno。
不同的编译器有不同的 TLS 标准。
g++/clang++/xlc++ 可以看到如下语法:
__thread int errCode;
每个线程拥有独立的 errCode 的拷贝,一个线程中的 errCode 的读写并不会影响另一个线程中的 errCode。
C++11 对 TLS 标准做了统一的规定。
int thread_local errCode;
对 thread_local 变量地址取值(&),也只能获得当前现场中 TLS 变量的地址值。