从上下文切换谈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 ...
随机推荐
- [Flink] Flink运行过程中Flink作业运行崩溃,且`TaskManager`报:"Association with remote system [akka.tcp://flink@flink-236429.ns-69020:6123] has failed, address is now gated for [50] ms. Reason: [Disassociated]"
1 问题描述 一个长期正常运行的FlinkSqlCdcJob(Flink 1.12 . Flink CDC 1.3.0),运行崩溃,且TaskManager的日志(taskmanager.log)报: ...
- 【Go】彩云小译翻译接口js逆向解密返回值
一.前言 对彩云小译网页版进行抓包分析,将js算法代码转换成go代码,使用go发送http请求编写一个翻译小工具. 主要实现: 翻译(解密翻译结果) 单词字典查询 生成JWT(保持有效期) 二.抓包 ...
- Linux 压缩命令集合
01. tar格式 解包:tar xvf FileName.tar 打包:tar cvf FileName.tar DirName(注:tar是打包,不是压缩!) 02. gz格式 解压1:gunzi ...
- 【Java RPC】使用netty手写一个RPC框架 结合新特性 虚拟线程
[手写RPC框架]如何使用netty手写一个RPC框架 结合新特性 虚拟线程 什么是RPC框架 RPC(Remote Procedure Call)远程过程调用,是一种通过网络从远程计算机程序上请求服 ...
- 日志数据采集-Flume
1. 前言 在一个完整的离线大数据处理系统中,除了hdfs+mapreduce+hive组成分析系统的核心之外,还需要数据采集.结果数据导出.任务调度等不可或缺的辅助系统,而这些辅助工具在hadoop ...
- java代码之美(2)
guava 复写Object常用方法 Guava 是一个 Google 的基于java1.6的类库集合的扩展项目,这个库提供用于集合,缓存,支持原语,并发性,常见注解,字符串处理,I/O和验证的实用方 ...
- 系统提示msvcp120.dll丢失如何解决
最近有位win7系统用户反映,自己安装完游戏开始玩的时候,系统却提示:示msvcp120.dll丢失,这导致了游戏无法正常运行,这让用户很是苦恼,不知道电脑如何解决,为此非常苦恼,那么win7系统提示 ...
- OS:MMU
MMU? 全称:memory management unit [内存管理单元] 是: 1.CPU中用来管理虚拟存储器.物理存储器的控制线路 2.同时也负责虚拟地址映射为物理地址 3.以及提供硬件机制的 ...
- Iceberg metrics导致的问题
一.问题描述 在iceberg rewrite时报错:org.apache.iceberg.exceptions.ValidationException: Cannot commit, found n ...
- spark-sql查询Iceberg时处理流程
1.查询表结构 show create table data_lake_ods.test CREATE TABLE spark_catalog.data_lake_ods.test ( `user_n ...

