Qt环境下普通变量与原子变量的区别与联系

一、定义

1.普通变量

int、bool、double、自定义变量

读写是拆分多条CPU微指令,不是一次性完成。

2.原子变量

std::atomic、QAtomicInteger、QAtomicBoolean

硬件层级一次性完整读写,中途不会被其他线程打断。

二、核心区别

1、执行指令

  • 普通变量

赋值/自增是多步指令,例: a++

1)从内存读a到CPU

2)CPU计算+1

3)写回内存

多线程会穿插插队,数据覆盖错乱。

​- 原子变量

a++ 整条指令不可拆分,执行中其他线程强制阻塞,不会插队。

2、多线程安全

  • 普通变量:多线程同时读写=数据竞争、脏数据、程序崩溃

​- 原子变量:天生线程安全,无需加锁

3、内存排序(指令重排)

  • 普通变量:编译器/CPU会乱序优化指令,多线程逻辑错乱

​- 原子变量:禁止指令重排,执行顺序固定

4、性能

1)普通变量:速度最快,无任何限制

2)原子变量:比普通慢一点、比mutex锁快非常多

5、使用范围

  • 普通变量:所有类型、结构体、字符串、对象都能用

  • 原子变量:只支持int、bool、long基础简单类型,结构体不可用

三、联系

1.本质都是内存存放的数据,占用内存方式一致。

2.原子变量是给普通变量加硬件防护buff。

3.都是用来存数值、状态标记。

速度:普通变量>原子变量>互斥锁mutex

安全:mutex>原子变量>普通变量

四、使用场景划分

1.单纯状态标记、开关、计数、循环标志

👉用原子变量,无锁高效

2.字符串、结构体、多步复杂赋值

👉普通变量+QMutex互斥锁

3.单线程所有变量全部用普通变量,无区别。

五 结构体变量多个线程的互斥操作

添加头文件 #include <QMutex>

// 复杂结构体互斥示例

struct MyData {

int a;

QString s; // 非平凡拷贝

};

MyData shared_data;

QMutex data_mutex; // 保护锁

void thread_safe_write() {

QMutexLocker locker(&data_mutex); // 自动加锁/解锁

shared_data.a = 20;

shared_data.s = "hello";

}

void thread_safe_read() {

QMutexLocker locker(&data_mutex);

qDebug() << shared_data.a << shared_data.s;

}

复杂结构体(含QString/指针) 一般采用 QMutex + QMutexLocker组合使用(安全、通用)。

注意:不需要为每个线程单独定义QMutex。

1)锁是保护【共享数据】的,不是保护【线程】的。

​2) 一份共享数据 → 只需要一把锁。

​3.)所有访问这份数据的线程,都共用这一把锁。

相关推荐
慧都小项3 天前
当边缘AI上产线:QtitanDocking 如何让工业 HMI 实现多视图协同
人工智能·qt·ui·边缘计算·qt6.3
Quz3 天前
QML SwipeDelegate 滑动委托
qt
Quz3 天前
QML 列表中的四种委托:ItemDelegate、CheckDelegate、RadioDelegate、SwitchDelegate
qt
实心儿儿3 天前
Qt — 显示类控件
qt
江湖人称菠萝包4 天前
【Qt】《Qt 5.9 C++开发指南》笔记-Chapter9-Qt Charts
笔记·qt·qt5
扶尔魔ocy4 天前
【QT android】环境安装及第一个QT项目
qt·andriod开发
江湖人称菠萝包4 天前
【Qt】《Qt 5.9 C++开发指南》笔记-Chapter10-Data Visualization
笔记·qt·qt5
Cx330❀4 天前
Qt 常用控件属性与底层机制详解:从窗口半透明、浮点数陷阱到 QSS 与焦点策略
qt·ui·图形渲染
Quz4 天前
QML DelegateChooser:多条件组合与按列选择委托
qt
Quz4 天前
QML DelegateChooser:按角色选择委托与按索引选择委托
qt