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 = 1;

void f()
{
    g_n++;
    printf("id=%d, n=%d\n", std::this_thread::get_id(),g_n);
} void foo()
{
    thread_local int i=0;
    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 0;
}

输出(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

 
from:http://www.cnblogs.com/pop-lar/p/5123014.html

最新文章

  1. Core Java 总结(字符和字符串类问题)
  2. rpm 更新/升级 软件包(libGL-devel手动安装过程)
  3. Control Flow in Async Programs
  4. DNF技能贴图的研究
  5. TP开发小技巧
  6. 89、instancetype和id的区别
  7. MFC笔记10
  8. 笔记-返回到前一个页面时显示前一个页面中ajax获取的数据
  9. 【Linux高级驱动】如何分析并移植网卡驱动
  10. 百度地图API示例:鼠标绘制点线面 控件修改
  11. ASP.NET批量下载文件
  12. valgrind--CPP程序内存泄露检查工具
  13. 小程序中bindtap绑定函数,函数参数event对数据的处理
  14. window下redis nosql初试
  15. 修改nginx的http响应头server字段
  16. JVM体系结构之七:持久代、元空间(Metaspace) 常量池==了解String类的intern()方法、常量池介绍、常量池从Perm--&gt;Heap
  17. LeetCode—Minimum Size Subarray Sum
  18. loadView 与 viewDidLoad 和 didReceiveMemoryWarning与viewDidUnload 详解
  19. Codeforces Round #510 (Div. 2) B. Vitamins
  20. 用new Image().src作LOG统计的一个注意事项 .

热门文章

  1. java常用封装方法
  2. 51nod 1128 二分
  3. xftp5+xshell5工具安装包分享
  4. JavaScript实现文章复制加版权信息
  5. LeetCode OJ:Sort Colors(排序颜色)
  6. 微信小程序 报错Setting data field &quot;variableName&quot; to undefined is invalid.
  7. 横向排列两个多个div盒子的方法(CSS浮动清除float-clear/inline)/办法
  8. python exec内置表达式--exec()
  9. BZOJ3141:[HNOI2013]旅行
  10. poj 2096 , zoj 3329 , hdu 4035 —— 期望DP