线程局部存储

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 变量的地址值。

上一篇下一篇

猜你喜欢

热点阅读