从上下文切换谈thread_local工作原理
从上下文切换谈thread_local工作原理
thread_local是什么
熟悉多线程编程的小伙伴一定对thread_local不陌生,thread_local 是 C++11 引入的一种存储类说明符,用于定义每个线程都有其独立实例的变量。每个线程对这些变量有自己的副本,而不共享其他线程的副本。这在多线程编程中非常有用,确保线程之间的数据隔离,防止数据竞争。
但是thread_local的表现又很奇怪,你说它是全局变量吧,但它又被每个线程私有,比如下面这个例子:
#include <iostream>
#include <thread>
#include <stdio.h>
// 定义一个 thread_local 变量
thread_local int local_var = 0;
void thread_function(int id) {
local_var = id;
printf("%x\n", &local_var);
}
int main() {
std::thread t1(thread_function, 1);
std::thread t2(thread_function, 2);
t1.join();
t2.join();
return 0;
}
输出:

地址不同,说明两个线程里的local_var变量不是同一个。
但是你说它是局部变量吧,它的生命周期又很长,thread_local 变量的生命周期从线程创建时开始,到线程结束时结束。
其实抽象出它的具体含义就是:
每个线程独立实例: 每个线程对
thread_local变量都有自己的独立副本,不会与其他线程的副本共享。生命周期:
thread_local变量的生命周期从线程创建时开始,到线程结束时结束。
那么问题来了,每个线程都有自己的独立副本,在访问的时候又互不影响,这个是怎么实现的呢?这就引出了上下文切换这个概念。
上下文切换
我们先看一下最开始的thread_function对应的汇编代码:
![]() |
![]() |
|---|
寄存器fs记录了当前正在运行的线程所有的thread_local变量所在内存块的首地址。不同的线程,它的上下文也是不同的,所以寄存器fs的值也是不同的;这样就非常巧妙的通过线程的上下文切换区分了不同线程对应的thread_local;
如图:

假设现在线程1正在执行,操作系统会创建线程1的上下文,上下文一般是指当前寄存器的值,他们包含了当前程序运行的状态,比如栈指针esp,程序计数器eip,在此例中也包含fs,fs记录了当前线程栈上的thread_local变量的起始地址。
同理我们再创建另一个线程2:

线程1和线程2对应着程序运行栈上的不同区域,因此他们的fs寄存器的值也是不同的。所以当发生线程上下文切换的时候,操作系统会恢复将要运行的线程的上下文(寄存器状态)。这样每个线程也就能自然通过fs对应到它的thread_local变量。
总结
本篇博文先是介绍了thread_local的特性:
每个线程独立实例: 每个线程对
thread_local变量都有自己的独立副本,不会与其他线程的副本共享。生命周期:
thread_local变量的生命周期从线程创建时开始,到线程结束时结束。
然后通过上下文切换的概念介绍了实现的方法。有关更多上下文切换的内容,可参照《CPU眼中的C++》5.8节。
refer
《CPU眼中的C++》
从上下文切换谈thread_local工作原理的更多相关文章
- 浅谈React工作原理
浅谈React工作原理:https://www.cnblogs.com/yikuu/p/9660932.html 转自:https://cloud.tencent.com/info/63f656e0b ...
- [iOS]浅谈NSRunloop工作原理和相关应用
一. 认识NSRunloop 1.1 NSRunloop与程序运行 那么具体什么是NSRunLoop呢?其实NSRunLoop的本质是一个消息机制的处理模式.让我们首先来看一下程序的入口——main ...
- TODO:浅谈pm2基本工作原理
TODO:浅谈pm2基本工作原理 要谈Node.js pm2的工作原理,需要先来了解撒旦(Satan)和上帝(God)的关系. 撒旦(Satan),主要指<圣经>中的堕天使(也称堕天使撒旦 ...
- 浅谈dedecms模板引擎工作原理及其自定义标签
浅谈dedecms模板引擎工作原理: 理解织梦模板引擎有什么意思? 可以更好地自定义标签.更多在于了解织梦系统,理解模板引擎是理解织梦工作原理的第一步. 理解织梦会使我们写PHP代码是更顺手,同时能学 ...
- [转自SA]浅谈nginx的工作原理和使用
nginx apache 简单对比 nginx 相对 apache 的优点: 轻量级,同样起web 服务,比apache 占用更少的内存及资源 抗并发,nginx 处理请求是异步非阻塞的,而 apac ...
- (转)浅谈dedecms模板引擎工作原理及自定义标签
理解织梦模板引擎有什么意义?一方面可以更好地自定义标签.更多在于了解织梦系统,理解模板引擎是理解织梦工作原理的第一步.理解织梦会使我们写php代码时更顺手,同时能学习一些php代码的组织方式. 这似乎 ...
- 浅谈malloc()和free()工作原理
编程之路刚刚开始,错误难免,希望大家能够指出. malloc()和free()是我经常需要用到的函数,一般情况下,C程序使用malloc()在堆上分配内存,free()释放内存,两者的参数和返回值就 ...
- 浅谈C++编译原理 ------ C++编译器与链接器工作原理
原文:https://blog.csdn.net/zyh821351004/article/details/46425823 第一篇: 首先是预编译,这一步可以粗略的认为只做了一件事情,那就 ...
- 【夯实Nginx基础】Nginx工作原理和优化、漏洞
本文地址 原文地址 本文提纲: 1. Nginx的模块与工作原理 2. Nginx的进程模型 3 . NginxFastCGI运行原理 3.1 什么是 FastCGI ...
- Nginx 工作原理和优化、漏洞
1. Nginx的模块与工作原理 Nginx由内核和模块组成,其中,内核的设计非常微小和简洁,完成的工作也非常简单,仅仅通过查找配置文件将客户端请求映射到一个location block(locat ...
随机推荐
- C Primer Plus 第6版 第五章 编程练习参考答案
编译环境VS Code+WSL GCC 源码在文末下载 /*第1题*************************/ #include<stdio.h> #define MIN_TO_H ...
- 微服务实战系列(九)-注册中心与网关高可用架构设计-copy
1. 微服务关系架构图 简要说明: (1)所有应用或者服务要想对外提供服务(包括网关),必须首先到注册中心进行注册. (2)所有访问通过服务网关进行访问,然后由服务网关路由到对应服务中心进行交互访问. ...
- 使用pict生成正交表
使用pict可以自动生成正交表 步骤: 1.安装 2.新建TXT文件,格式为: 因子1:水平项1,水平项2 因子2:水平项1,水平项2 多个水平项用英文逗号分割 3.生成,打开cmd,切换到要 ...
- 类的加载与ClassLoader的理解
加载:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口(即引用地址).所 ...
- vscode python remote debug极速入门
本文适用范围 主要适用于debug python 程序,尤其是深度学习刚入门需要使用remote 连接到linux进行程序运行,想调试一下的同学. 当然非深度学习也可以参考食用本文哈哈哈. 极速入门版 ...
- 「CF 123E」Maze
传送门 题意澄清 对于 dfs 遍历时,在某一个点进入子树的顺序并不是按输入顺序,而是假定随机选择未进入过的子树 (这纠结了我好久) . 破题思路 首先可以明确这题不能推一个 \(O(1)\) 的式子 ...
- uni-app之条件编译
ifdef 仅出现在XXx平台上 仅出现在 App 平台下的代码 #ifdef APP-PLUS 需条件编译的代码 #endif <!-- 只在H5上有哈 --> <!-- #ifd ...
- DeepSeek-R1 技术全景解析:从原理到实践的“炼金术配方” ——附多阶段训练流程图与核心误区澄清
字数:约3200字|预计阅读时间:8分钟 (调试着R1的API接口,看着控制台瀑布般流淌的思维链日志)此刻我仿佛看到AlphaGo的棋谱在代码世界重生--这是属于推理模型的AlphaZero时刻. D ...
- 使用必读-使用Iceberg数据湖需要注意的点
一.开发注意事项 1.Iceberg选择合适的表版本 简述:Iceberg目前有两个表版本(V1和V2),根据数据选择合适的表版本. V1表只支持增量数据插入,适合做纯增量写入场景,如埋点数据. V2 ...
- LangChain基础篇 (05)
LangChain 核心模块:Data Conneciton - Document Transformers 一旦加载了文档,通常会希望对其进行转换以更好地适应您的应用程序. 最简单的例子是,您可能希 ...

