【C/C++】多线程读写普通 int 变量的一些问题

多线程读写普通int变量问题

场景:线程A写普通int,线程B读同一个普通int,无锁、无volatile。

前提:int在当前平台是32位,对齐访问。

1、会不会出现"字节撕裂(半写值)"?

  • x86/x64:对齐的32位int,读写是原子的CPU指令,写的时候不会读到一半字节,不会读到一个一半旧一半新的畸形数值。

⚠️ 注意:64位long long在32位系统就不是原子,会出现撕裂;但32位对齐int不会。

但!原子 ≠ 线程安全!这是最容易踩坑的地方。

虽然不会读到破碎值,但依然有两个严重问题:可见性问题 、指令重排序问题。


2、可见性问题(CPU缓存)

每个CPU核心有私有L1/L2缓存。

  1. 线程A(CPU0)修改int,新值先写到CPU0缓存,不一定立刻刷回主内存。
  2. 线程B(CPU1)读变量,读的是CPU1自己缓存里的旧副本。

现象:

A已经把x=100,B可能长期读到旧值x=0,永远看不到新修改。

这就是缓存可见性失效。

3、编译器 / CPU指令重排序

编译器、CPU会为性能打乱指令执行顺序,只要单线程逻辑不变。

示例伪代码:

c 复制代码
int flag = 0;
int data = 0;

//线程A
data = 123;
flag = 1;  //通知线程B数据准备好了

//线程B
if(flag == 1){
    print(data);
}

重排序后,线程A实际执行顺序可能变成:

c 复制代码
flag = 1;
data = 123;

线程B看到flag=1,去读data,读到还没更新的旧值。

普通int没有任何屏障,编译器和CPU都可以重排读写。

4、总结现象(普通int,无volatile无锁)

  1. ✅ 对齐32‑bit int:不会发生值撕裂,不会读到半个更新的乱码数字
  2. ❌ 读线程可能一直读到旧值(缓存可见性)
  3. ❌ 指令重排序,读写顺序被打乱,业务逻辑错乱
  4. ❌ 不能保证读到最新写入的值

很多人误以为:int读写原子就不用锁,这是错误。原子只保证不会读到破碎字节,不保证可见性、不保证顺序。


5、怎么解决

C/C++

  1. volatile int x
    • 阻止编译器优化,但是不能阻止CPU硬件重排序、缓存同步,现代多核下不完全可靠,不推荐用于线程同步。
  2. std::atomic<int> x ✅推荐
    • 硬件原子读写,自带内存屏障,解决可见性+重排序。读x.load(),写x.store()。
  3. 互斥锁mutex保护读写。

Java

  • volatile int x:禁止重排序、保证可见性;32位int读写原子。

补充边界案例

  1. 如果int没有内存对齐 (刻意偏移),哪怕32位int,读写不再是CPU原子操作,就会出现值撕裂,读到一半旧一半新的数值。
  2. 64位long long,32位操作系统,普通读写不是原子,一定会撕裂。

最简记忆

对齐32位int:读写指令原子,但不代表线程安全。原子=不会碎;线程安全=可见+有序。两者不是一回事。

如果你需要,我可以写一小段可复现的C++示例代码,演示"写了但是读不到新值"这个现象。

相关推荐
知守观1 分钟前
多模块架构演进:横向分层 vs 纵向领域,13 个真实项目的切分对照
java·后端·微服务
UIU1149 分钟前
P16237 [蓝桥杯 2026 省 B] 应急布线
数据结构·c++·算法·蓝桥杯
raindayinrain10 分钟前
c++设计模式
开发语言·c++·设计模式
旖旎夜光13 分钟前
LeetCode 315: 算右侧小于当前元素的个数(归并排序) —— 题解
c++·学习·算法·leetcode·排序算法
Java成神之路-16 分钟前
Java String 为什么不可变?和 HashMap 到底有什么关系?
java
paopaokaka_luck20 分钟前
基于springboot+vue的益暖微光公益服务平台(DeepSeek公益助手、善款信息追溯、志愿服务积分闭环、ECharts运营分析、活动状态自动流转)
java·前端·javascript·spring boot·mysql·架构·echarts
D e re k ZH27 分钟前
保序回归:从 PAVA 到可并堆的单调约束优化
c++·算法·数据挖掘·回归·kotlin
青少儿编程课堂28 分钟前
蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级:字典树前缀树与单词检索统计
c++·python·算法·bfs·信息学竞赛
文丑颜不良啊30 分钟前
LeetCode1401~1420题目解析
java·leetcode
Nuanyt32 分钟前
LeetCode Hot 100 链表专题2 3 题 (Java)
java·笔记·算法·leetcode·链表