thread_local变量是C++ 11新引入的一种存储类型。它会影响变量的存储周期(Storage duration),C++中有4种存储周期:

  1. automatic
  2. static
  3. dynamic
  4. thread

有且只有thread_local关键字修饰的变量具有线程周期(thread duration),这些变量(或者说对象)在线程开始的时候被生成(allocated),在线程结束的时候被销毁(deallocated)。并且每 一个线程都拥有一个独立的变量实例(Each thread has its own instance of the object)。thread_local 可以和staticextern关键字联合使用,这将影响变量的链接属性(to adjust linkage)。

那么,哪些变量可以被声明为thread_local?以下3类都是ok的

  1. 命名空间下的全局变量
  2. 类的static成员变量
  3. 本地变量

下面引用《C++ Concurrency in Action》书中的例子来说明这3种情况:

thread_local int x;  //A thread-local variable at namespace scope
class X
{
    static thread_local std::string s; //A thread-local static class data member
};
static thread_local std::string X::s;  //The definition of X::s is required void foo()
{
    thread_local std::vector<int> v;  //A thread-local local variable
}

既然每个线程都拥有一份独立的thread_local变量,那么就有2个问题需要考虑:

  1. 各线程的thread_local变量是如何初始化的
  2. 各线程的thread_local变量在初始化之后拥有怎样的生命周期,特别是被声明为thread_local的本地变量(local variables)

下面的代码可以帮助回答这2个问题,我的测试环境是vs2015。

输出的前3行打印能帮助解答thread_local变量是如何初始化的,可以看到每个线程都会进行一次初始化,例子中的g_n在主线程中最早被初始化为1,随后被修改为2和3,但这些修改操作并不影响g_n在线程t2和t3中的初始值(值为1),虽然t2和t3线程启动的时候主线程中的变量值已经被更新为3,所以主线程、thread1、thread2打印结果分别为3,2,2。

后6行打印说明了一个事实,声明为thread_local的本地变量在线程中是持续存在的,不同于普通临时变量的生命周期,它具有static变量一样的初始化特征和生命周期,虽然它并没有被声明为static。例子中foo函数中的thread_local变量 i 在每个线程第一次执行到的时候初始化,在每个线程各自累加,在线程结束时释放。

#include <thread>

thread_local int g_n = ;

void f()
{
    g_n++;
    printf("id=%d, n=%d\n", std::this_thread::get_id(),g_n);
} void foo()
{
    thread_local int i=;
    printf("id=%d, n=%d\n", std::this_thread::get_id(), i);
    i++;
} void f2()
{
    foo();
    foo();
} int main()
{
    g_n++; 
    f();    
    std::thread t1(f);
    std::thread t2(f);
    
    t1.join();
    t2.join();     f2();
    std::thread t4(f2);
    std::thread t5(f2);     t4.join();
    t5.join();
    return ;
}

输出(id值是每次运行时变的):

id=8004, n=3

id=8008, n=2
id=8012, n=2
id=8004, n=0
id=8004, n=1
id=8016, n=0
id=8016, n=1
id=8020, n=0
id=8020, n=1

thread_local变量的更多相关文章

  1. thread_local变量(转)

    转自:https://www.cnblogs.com/pop-lar/p/5123014.html thread_local变量是C++11新引入的一种存储类型.它会影响变量的存储周期(Storage ...

  2. c/c++ 多线程 thread_local 类型

    多线程 thread_local 类型 thread_local变量是C++ 11新引入的一种存储类型. thread_local关键字修饰的变量具有线程周期(thread duration), 这些 ...

  3. c++11: thread_local

    thread_local变量是C++ 11新引入的一种存储类型.它会影响变量的存储周期(Storage duration),C++中有4种存储周期: automatic static dynamic ...

  4. [c++] Pieces of knowledge

    再系统地学一遍c++,查缺补漏. wchar_t L'a' stored in wchar_t. size of types cout << numeric_limits<doubl ...

  5. C++14介绍

    C++14标准是 ISO/IEC 14882:2014 Information technology -- Programming languages -- C++ 的简称[1]  .在标准正式通过之 ...

  6. C++11 (多线程)并发编程总结

    | 线程 std::thread 创建std::thread,一般会绑定一个底层的线程.若该thread还绑定好函数对象,则即刻将该函数运行于thread的底层线程. 线程相关的很多默认是move语义 ...

  7. Linux 调试: systemtap

    安装与配置 在ubuntu下直接用apt-get install之后不能正常使用,提示缺少调试信息或者编译探测代码时有问题. 1. 采用官网上的解决方法 2. 可以自己重新编译一次内核,然后再手工编译 ...

  8. C++11并发编程个人小结

    thread_local变量在每个线程第一次执行到时初始化(类似static),并在每个线程各自累加,并在线程结束时释放. std::condition_variable:: wait(std::un ...

  9. C++的各种初始化方式

    C++小实验测试:下面程序中main函数里a.a和b.b的输出值是多少? #include <iostream> struct foo { foo() = default; int a; ...

随机推荐

  1. python学习笔记(excel简单操作)

    现在的目标是设计一个接口自动化测试框架 用例写在excel里面 利用python自带的pyunit构建 之前已经安装好了处理excel的模块 这次简单的使用下 提前创建好excel文件 “testca ...

  2. Appium 自动化测试(2)--环境安装:安装Android模拟器

    一.安装java 环境-JDK 略,自行百度安装. 二.安装Android SDK Android SDK提供给我们API库和开发工具构建,测试和调试应用程序,Android.简单来讲,Android ...

  3. DESUtil 加密算法

    import java.security.Key; import java.security.Security; import javax.crypto.Cipher; /** *@Title: DE ...

  4. lambda表达式----使用

    List<THealthKnowledgeEntity> tHealthKnowledgeList = tHealthKnowledgeService.queryList(query);L ...

  5. JDeveloper 10g Certified on Windows 10 for EBS 12.1

    JDeveloper 10g is now certified for Windows 10 desktops for Oracle E-Business Suite 12.1.  See: Reco ...

  6. .html() .text() .val() 的区别

    .html()用为读取和修改元素的HTML标签(包括其Html标签) .text()用来读取或修改元素的纯文本内容 (包括其后代元素) .val()用来读取或修改表单元素的value值.(只能用于表单 ...

  7. git修改远端服务器地址

    方法有三种: 1.修改命令 git remote set-url origin [url] 2.先删后加 git remote rm origingit remote add origin [url] ...

  8. commond prompt CD

    如果要进入目前所在盘符的其他路径用cd命令可进入,但如果从c盘进入d盘等,是不用cd命令的. 如目前在c盘的任意目录,需要切换到d盘的根目录,用:“d:”命令(不含引号),如图: cd命令简介: 第一 ...

  9. 项目工程结构说明(Internal)

    注意:想要彻底把Internal关键字搞清楚,就耐着性子把她读完.当然了这篇文章只是对其他文章的总结.也算是引用吧.主要还是为了把知识点搞清楚 进入主题之前先来了解一下,项目.解决方案.程序集.命名空 ...

  10. 持久层框架:MyBatis 3.2(2)

    每个MyBatis应用程序主要都是使用SqlSessionFactory实例的,一个SqlSessionFactory实例可以通过SqlSessionFactoryBuilder获得.SqlSessi ...