「这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战」
thread_local
thread_local变量允许你为程序中的每个线程拥有一个单独的变量实例。thread_local可以用来声明以下类型的变量:
- 命名空间内的变量
- 类的静态数据成员
- 局部变量 如:
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变量引用传到另一个线程,但要确保这个变量在使用时没有析构,否则会引发未定义的行为。