0

0

c++中的volatile关键字有什么用_c++多线程与嵌入式编程关键【详解】

冰火之心

冰火之心

发布时间:2025-12-26 13:59:56

|

417人浏览过

|

来源于php中文网

原创

volatile关键字核心作用是禁止编译器优化,强制每次访问都读写内存,适用于硬件寄存器等外部修改场景;它不提供原子性、内存序或线程安全,多线程中须用std::atomic或mutex。

c++中的volatile关键字有什么用_c++多线程与嵌入式编程关键【详解】

volatile 关键字在 C++ 中的核心作用是:告诉编译器“这个变量的值可能在任何时候被外部因素改变,不要对它做优化假设”。它不解决多线程同步问题,也不提供原子性或内存序保证——这是很多人误用它的根本原因。

volatile 防止编译器过度优化

编译器在优化时,可能把多次读取同一个变量的代码合并成一次(比如缓存到寄存器),或直接删掉看似“无用”的读写。而某些场景下,变量值其实由硬件、中断服务程序、其他 CPU 核心等外部机制修改,编译器无法感知。

加上 volatile 后,每次访问该变量都会强制从内存(或对应寄存器地址)重新读取或写入,不跳过、不重排、不缓存。

  • 常见于嵌入式开发:如状态寄存器、GPIO 寄存器、ADC 数据寄存器
  • 示例:volatile uint32_t* const pReg = (uint32_t*)0x40001000; —— 每次 *pReg 都真实读硬件
  • 中断服务函数中修改的全局标志变量,主循环里检查它,也常加 volatile(但注意:仅防优化,不保线程安全)

volatile 不等于线程安全

这是 C++ 多线程中最常见的误解。volatile 不能替代 std::atomic 或互斥锁:

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

AI帮个忙
AI帮个忙

多功能AI小工具,帮你快速生成周报、日报、邮、简历等

下载
  • 它不阻止 CPU 指令重排序(CPU 层面的乱序执行依然可能发生)
  • 它不保证读写操作的原子性(比如 volatile int 变量在某些平台上的写仍是两步)
  • 它不提供 happens-before 关系,无法建立线程间同步语义
  • 多个线程同时读写一个 volatile 变量,仍属未定义行为(UB)

正确做法:多线程共享变量请用 std::atomic(带内存序控制),需要临界区则用 std::mutex 等同步原语。

嵌入式中 volatile 的典型使用场景

嵌入式系统里,volatile 的价值更明确,因为它直面硬件不可预测性:

  • 外设寄存器映射:所有 MMIO(Memory-Mapped I/O)地址对应的变量都应为 volatile
  • 中断标志位:如 UART 接收完成标志,由硬件置位,软件轮询清零
  • DMA 缓冲区描述符:硬件和 CPU 共享的结构体字段,需确保每次访问都生效
  • 信号量或简单状态机标志(仅限单核 + 中断上下文):如 volatile bool ready = false; 中断里设 true,主循环 while(!ready); —— 此处 volatile 防止编译器优化成死循环

和 std::atomic 的关键区别

两者目标不同,不能混用或互换:

  • volatile:面向「可见性」+「禁优化」,对象语义仍是普通类型(无原子操作、无内存序)
  • std::atomic:面向「并发安全」,提供原子读写、CAS、内存序(memory_order_relaxed/seq_cst 等)
  • 可以同时用:std::atomic flag{0}; 是线程安全的;volatile std::atomic 几乎没意义(atomic 已自带 volatile 效果)
  • 特别注意:volatile intstd::atomic_int 表面相似,但后者才真正跨线程可靠

基本上就这些。volatile 是嵌入式开发的必备工具,但在多线程通用编程中要格外谨慎——它不是同步机制,只是编译器的“别动这个变量”的提醒。真正需要并发保护的地方,交给 atomic 和 mutex。

相关专题

更多
while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

80

2023.09.25

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

517

2023.09.20

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

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

193

2025.06.09

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

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

184

2025.07.04

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

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

193

2025.06.09

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

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

184

2025.07.04

string转int
string转int

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

311

2023.08.02

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

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

512

2024.08.29

虚拟号码教程汇总
虚拟号码教程汇总

本专题整合了虚拟号码接收验证码相关教程,阅读下面的文章了解更多详细操作。

25

2025.12.25

热门下载

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

精品课程

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

共578课时 | 37.8万人学习

国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 0.9万人学习

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

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