0

0

C++多线程中的伪共享(False Sharing)是什么?(如何避免)

尼克

尼克

发布时间:2025-12-21 15:18:08

|

310人浏览过

|

来源于php中文网

原创

伪共享是多线程中因不同变量同处一缓存行引发的性能瓶颈:一核写导致整行失效,他核读写需重加载,造成缓存行颠簸;根源在于CPU以64字节缓存行为单位管理内存,且仅并发写才触发问题。

c++多线程中的伪共享(false sharing)是什么?(如何避免)

伪共享是多线程程序中一种隐蔽的性能瓶颈:多个线程频繁修改位于同一CPU缓存行(通常是64字节)但逻辑上无关的变量,导致缓存行在核心间反复无效化和同步,严重拖慢执行速度。

为什么会出现伪共享

CPU以缓存行为单位加载和写回内存。即使两个变量在代码中完全独立、分属不同线程,只要它们在内存中地址相近(比如相邻成员变量、数组相邻元素),就可能落入同一缓存行。当一个线程修改其中某个变量时,整个缓存行被标记为“已修改”,其他核心上该行副本立即失效;另一线程读/写同行内另一变量时,必须重新从内存或其它核心拉取整行——这叫“缓存行颠簸”(cache line bouncing)。

Type Studio
Type Studio

一个视频编辑器,提供自动转录、自动生成字幕、视频翻译等功能

下载

典型伪共享场景

结构体成员挤在一起 多个线程各自更新不同对象的某个字段(如 counter),但这些对象是连续分配的数组,且 counter 在结构体开头或未对齐:

struct alignas(64) PaddedCounter {  // 对齐到64字节边界
    std::atomic value{0};
    char _pad[64 - sizeof(std::atomic)]; // 填充至一整行
};
std::vector counters(4); // 每个counter独占一行

数组元素被不同线程轮着改 比如4个线程分别累加 arr[0]arr[1]arr[2]arr[3],而 sizeof(int) == 4,64字节能塞16个int——前4个很可能同属一行。

避免伪共享的实用方法

手动填充(Padding)alignas(64) 强制结构体按缓存行对齐,并在热点变量后补足空间,确保它独占一行。注意:仅对真正被多线程并发写的变量做填充,别盲目加。

重排数据布局 把会被同一线程访问的变量放一起(提高局部性),把被不同线程写的变量尽量拉开距离。例如用结构体数组(AOS)改成数组结构体(SOA):把所有线程的 x 存一起、所有 y 存一起,再按线程号索引,减少跨行访问。

使用线程局部存储(TLS)+ 合并汇总 每个线程先写自己的本地计数器(如 thread_local int local_count),最后单线程合并到全局变量。避免任何跨线程写竞争。

确认是否真有伪共享 别靠猜测优化。用 perf(Linux)看 cache-missesLLC-load-misses 是否异常高;或用 VTune、perf annotate 定位热点指令的内存访问模式。有时候看似伪共享,其实是锁争用或内存带宽不足。

基本上就这些。伪共享不复杂但容易忽略,关键在“写”——只读不会触发无效化,只有并发写才危险;排查时优先看数据布局和缓存行对齐,而不是一上来就改算法。

相关专题

更多
全局变量怎么定义
全局变量怎么定义

本专题整合了全局变量相关内容,阅读专题下面的文章了解更多详细内容。

77

2025.09.18

python 全局变量
python 全局变量

本专题整合了python中全局变量定义相关教程,阅读专题下面的文章了解更多详细内容。

96

2025.09.18

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

196

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

187

2025.07.04

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

315

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

538

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

52

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

197

2025.08.29

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

9

2026.01.16

热门下载

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

精品课程

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

共48课时 | 7.3万人学习

Git 教程
Git 教程

共21课时 | 2.7万人学习

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

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