C++-thread_local

1,173 阅读2分钟

「这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战

thread_local

thread_local变量允许你为程序中的每个线程拥有一个单独的变量实例。thread_local可以用来声明以下类型的变量:

  1. 命名空间内的变量
  2. 类的静态数据成员
  3. 局部变量 如:

thread_local int x; //类型1

class X

{

static thread_local std::string s; //类型2

};

static thread_local std::string X::s; //静态数据成员需要定义

void foo()

{

thread_local std::vector<int> v; //类型3

}

thread_local变量具有线程存储周期( thread storage duration)。对于类型12来说,编译器实现能保证在第一次使用前thread_local变量会被构造,至于是线程开始时,或是第一次使用前一刻,或是基于变量的使用上下文决定都不一定。事实上,如果变量没有被使用,可能甚至不会被构造出来。

对于类型3,在声明处变量就被构造,如果函数未被调用(对每个线程来说),则变量不会被构造。

thread_local变量会先被零初始化,然后再被进一步初始化,如果变量构造过程发生异常,std::terminate()将会被调用,程序终止。

当线程函数退出或者调用std::exit()时,thread_local变量被析构,析构顺序与构造顺序相反。因为前述原因,构造顺序不确定,所以析构顺序不确定,所以我们要确保thread_local变量之间的析构函数没有依赖关系,如果析构发生异常,std::terminate()将会被调用。

如果程序停止时部分线程还未退出,则那些线程的thread_local变量不会析构。

每个线程的thread_local变量都不同,我们可以将一个线程的thread_local变量引用传到另一个线程,但要确保这个变量在使用时没有析构,否则会引发未定义的行为。