C++之thread

2024-06-25 1493阅读

目录

C++之thread
(图片来源网络,侵删)

1.C++ 的存储类型

1.1.存储周期(Storage duration)

1.2.存储类型说明符(Storage class specifiers)

1.3.存储类型说明符与存储周期的关系

2.thread_local简介

3.thread_local 应用

3.1.thread_local 与全局变量

3.2.thread_local 与 static变量

3.3.thread_local 与 成员变量

3.4.thread_local 与初始化

4.thread_local 的用处

5.性能考虑

6.替代方案

7.总结


1.C++ 的存储类型

1.1.存储周期(Storage duration)

        存储周期表示一个变量的存储空间持续的时间,它应该与对象的语义生命周期一致(或至少不小于对象的语义生命周期)。C++ 98从 C 继承了三种存储周期,分别是静态存储周期(static storage duration)、自动存储周期(automatic storage duration)和动态存储周期(dynamic storage duration),C++ 11 又增加了一种线程存储周期(thread storage duration)。

        存储周期只是一个概念,是程序语义范畴内的东西,但不是语法的范畴。这个概念在语法上的表示则由下一节介绍的存储类型说明符(Storage class specifiers)展示。

1.2.存储类型说明符(Storage class specifiers)

        存储类型说明符(Storage class specifiers)也被称为存储类型,它们是变量声明语法中类型说明符的一部分,它们和变量名的范围一起控制变量的两个独立属性,即存储周期(storage duration)和链接属性( linkage)。C++ 98从 C 语言继承了 auto、register、static 和 extern 四种类型,同时补充了一种 mutable,C++ 11 针对线程存储周期又增加了一个线程本地存储的说明符 thread_local。关于这几个存储类型说明符的作用,请参考下表:

类型说明备注
auto自动存储周期,也是变量的默认存储类型,由变量的域范围决定变量的存储周期,比如局部变量的存储周期随着域的结束而结束,而全局变量的存储周期则与程序的运行时间一致从 C++11 开始,显示使用 auto 存储类型会导致编译错误。比如 auto int i; 会导致编译错误
register也是自动存储类型,不过暗示编译器会择机将其放置在寄存器中以提高数据存取的效率在 C++ 17 被移除标准,以后应避免使用这个存储类型
static静态或线程存储周期,采用内部链接(对于不属于匿名名字空间(anonymous namespace)的静态类成员,采用外部链接)static 表示一个对象具有静态存储持续周期。它的生命周期是程序的整个执行过程,其存储的值在程序启动之前只初始化一次
extern静态或线程存储周期,采用外部链接
mutable严格来说,这不是一种存储类型,因为它既不影响变量的存储周期,也不影响链接属性,它只是表示一种可以“不动声色”地修改常量对象成员的机会。
thread_local线程存储类型

1.3.存储类型说明符与存储周期的关系

C++ 中变量存储周期与变量类型说明符的关系如下表所示:

存储周期变量类型与类型说明符
自动存储周期显式使用 register 声明的变量,或隐式声明为 static 或 extern 的作用域内部变量,没有明确指定存储类型说明符的变量
静态存储周期1、非 thread_local 声明的全局(非局部)变量;2、非动态生成(使用 new 创建)的非局部变量;3、用 static 声明的局部变量、全局变量和类成员变量
动态存储周期1、使用 new 表达式创建(非 placement_new),并且使用 delete 销毁的对象;2、使用其他动态分配函数和动态释放函数管理的对象存储位置
线程存储周期使用 thread_local 声明的所有变量,包括局部变量、全局变量和成员变量

2.thread_local简介

        thread_local 是 C++11 为线程安全引进的变量声明符。表示对象的生命周期属于线程存储期。

        线程局部存储(Thread Local Storage,TLS)是一种存储期(storage duration),对象的存储是在线程开始时分配,线程结束时回收,每个线程有该对象自己的实例;如果类的成员函数内定义了 thread_local 变量,则对于同一个线程内的该类的多个对象都会共享一个变量实例,并且只会在第一次执行这个成员函数时初始化这个变量实例。

        thread_local 一般用于需要保证线程安全的函数中。本质上,就是线程域的全局静态变量。

3.thread_local 应用

3.1.thread_local 与全局变量

        使用 thread_local 声明的变量会在每个线程中维护一个该变量的实例,线程之间互不影响,这里我们用一个普通的全局变量和一个 thread_local 类型的全局变量做对比,说明一下这种存储类型的变量有什么性质。

std::mutex print_mtx;    //避免打印被冲断
thread_local int thread_count = 1;
int global_count = 1;
void ThreadFunction(const std::string& name, int cpinc)
{
    for (int i = 0; i 
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]