0

0

c++怎么在多线程中使用全局变量_c++线程局部存储【进阶】

尼克

尼克

发布时间:2026-03-05 14:41:03

|

409人浏览过

|

来源于php中文网

原创

全局变量在多线程中直接读写会导致数据竞争和未定义行为,因++等操作非原子,可能引发计数错误、崩溃或断言失败;应使用互斥锁(如std::mutex配合std::lock_guard)严格保护所有读写访问。

c++怎么在多线程中使用全局变量_c++线程局部存储【进阶】

全局变量在多线程中直接读写会出什么问题

直接用普通全局变量(比如 int g_counter = 0;)在多个线程里做 ++g_counter,结果几乎必然错误。这不是“偶尔错”,而是因为 ++ 不是原子操作:它包含读取、加1、写回三步,两个线程可能同时读到旧值,各自加1后写回,最终只+1而不是+2。

常见现象包括:计数远小于预期、程序崩溃(如多个线程同时 delete 同一指针)、数据结构(如 std::vector)内部状态不一致触发断言失败。

除非你明确做了同步,否则「全局变量 + 多线程」默认等于未定义行为。

怎么安全地共享全局状态:互斥锁是最常用解法

对共享全局变量加锁,是最直观、也最可控的方式。C++ 标准库提供 std::mutex 和 RAII 封装 std::lock_guard,避免忘记解锁。

立即学习C++免费学习笔记(深入)”;

  • 声明全局变量和配套互斥量要成对出现,且互斥量本身不能是局部静态或延迟初始化的(否则首次访问可能竞态)
  • 所有读写该变量的地方,必须用同一把锁保护;漏掉任意一处(比如只锁写不锁读),仍可能读到中间状态
  • 避免在锁内做耗时操作(如 I/O、sleep、调用未知第三方函数),否则拖慢整个线程池

示例:

AskManyAI
AskManyAI

AskManyAI是个一站式AI聚合平台,集成了国内外多个主流顶尖AI大模型

下载
int g_shared_data = 0;
std::mutex g_shared_mutex;

void thread_func() {
    for (int i = 0; i < 1000; ++i) {
        std::lock_guard<std::mutex> lk(g_shared_mutex);
        ++g_shared_data; // 安全
    }
}

什么时候该用 thread_local 而不是全局变量

thread_local 不是“线程安全的全局变量”,而是“每个线程一份独立副本”的变量。它解决的是**避免共享、消除同步开销**的问题,典型场景包括:

  • 缓存线程本地计算结果(如正则表达式编译对象、随机数引擎 std::mt19937
  • 避免频繁分配/释放资源(如线程专用的 std::string 或小内存池)
  • 封装非线程安全的 C 库上下文(如 errno 的替代、OpenSSL 的 ERR_get_error() 相关状态)

注意:thread_local 变量的构造和析构发生在对应线程的生命周期内,主线程的 main() 开始前和结束时各一次;新线程中首次访问时才构造。如果构造函数抛异常,该线程后续访问会再次尝试构造——这点容易被忽略。

std::atomic 能否替代 mutex 处理全局变量

可以,但仅限于简单类型(intbool、指针)的单一原子操作。例如 std::atomic_int g_counter{0}; 支持 g_counter.fetch_add(1) 这类无锁原子更新。

优势是无锁、低开销;劣势也很明确:

  • 不支持复合操作(比如“如果值为 X 则设为 Y,否则不变”需用 compare_exchange_weak 手动实现 CAS 循环)
  • 无法保护多个变量的关联更新(如同时改 g_xg_y 并保证二者一致性)
  • 对用户自定义类型,只有 trivially copyable 且满足特定对齐要求才能用 std::atomic<t></t>,且多数编译器实际只支持 lock-free 实现的子集

所以,别为了“看起来高级”硬套 std::atomic。该用锁的时候,锁更直白、更易维护。

真正容易被忽略的点是:thread_local 和 atomic 都解决不了「跨线程传递复杂状态」的问题。一旦你需要让线程 A 的某个中间结果被线程 B 精确观察到,就得回到同步原语(mutex / condition_variable / future)或者无锁数据结构的设计层面——那已经是另一个复杂度层级了。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

530

2023.06.20

正则表达式不包含
正则表达式不包含

正则表达式,又称规则表达式,,是一种文本模式,包括普通字符和特殊字符,是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式的文本。php中文网给大家带来了有关正则表达式的相关教程以及文章,希望对大家能有所帮助。

258

2023.07.05

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

765

2023.07.05

java正则表达式匹配字符串
java正则表达式匹配字符串

在Java中,我们可以使用正则表达式来匹配字符串。本专题为大家带来java正则表达式匹配字符串的相关内容,帮助大家解决问题。

219

2023.08.11

正则表达式空格
正则表达式空格

正则表达式空格可以用“s”来表示,它是一个特殊的元字符,用于匹配任意空白字符,包括空格、制表符、换行符等。本专题为大家提供正则表达式相关的文章、下载、课程内容,供大家免费下载体验。

356

2023.08.31

Python爬虫获取数据的方法
Python爬虫获取数据的方法

Python爬虫可以通过请求库发送HTTP请求、解析库解析HTML、正则表达式提取数据,或使用数据抓取框架来获取数据。更多关于Python爬虫相关知识。详情阅读本专题下面的文章。php中文网欢迎大家前来学习。

293

2023.11.13

正则表达式空格如何表示
正则表达式空格如何表示

正则表达式空格可以用“s”来表示,它是一个特殊的元字符,用于匹配任意空白字符,包括空格、制表符、换行符等。想了解更多正则表达式空格怎么表示的内容,可以访问下面的文章。

244

2023.11.17

正则表达式中如何匹配数字
正则表达式中如何匹配数字

正则表达式中可以通过匹配单个数字、匹配多个数字、匹配固定长度的数字、匹配整数和小数、匹配负数和匹配科学计数法表示的数字的方法匹配数字。更多关于正则表达式的相关知识详情请看本专题下面的文章。php中文网欢迎大家前来学习。

546

2023.12.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

2

2026.03.05

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 10.6万人学习

C 教程
C 教程

共75课时 | 5.2万人学习

C++教程
C++教程

共115课时 | 20.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号