【一篇即毕业系列】C++的volatile关键字从基础到通天。

文章目录

  • volatile关键字
    • [什么时候使用 volatile 关键字?](#什么时候使用 volatile 关键字?)
    • [volatile 修饰结构体时,结构体的成员也是 volatile 的吗](#volatile 修饰结构体时,结构体的成员也是 volatile 的吗)
    • volatile可以保证原子性吗
    • tips:

volatile关键字

本系列的所有文章都如同本章一样优秀,欢迎多多关注!

什么时候使用 volatile 关键字?

直接看下面代码:

cpp 复制代码
int a = 100;

while (a == 100) {
    // code
}

这段程序编译时,如果编译器发现程序始终没有企图改变a的值,那它可能就会优化这段代码,变成 while(true) 的死循环使得程序执行的更快,然而这种优化有时候会变成过度优化,编译器有时候可能没有意识到程序会改变a的值,却做了这种优化导致程序没有产生预期的行为。

这里为了产生预期的行为,需要阻止编译器做这种优化,可以使用 volatile 关键字修饰。

cpp 复制代码
volatile int a = 100;

volatile 关键字和 const 关键字相对应,const 关键字告诉编译器其修饰的变量是只读的,编译器根据只读属性做一些操作,而 volatile 关键字告诉编译器其修饰的变量是易变的,同理编译器根据易变属性也会做一些操作。它会确保修饰的变量每次都读操作都从内存里读取,每次写操作都将值写到内存里。

volatile 关键字就是给编译器做个提示,告诉编译器不要对修饰的变量做过度的优化,提示编译器该变量的值可能会以其它形式被改变。

volatile 修饰结构体时,结构体的成员也是 volatile 的吗

cpp 复制代码
struct A {
    int data;
};
volatile A a;
const A b;

答案是结构体内所有的都是 volatile,引用c++标准里的一句话:

Note: volatile is a hint to the implementation to avoid aggressive optimization involving the object because the value of the object might be changed by means undetectable by an implementation. See 1.9 for detailed semantics. In general, the semantics of volatile are intended to be the same in C ++ as they are in C.

这里大体可以理解为一个对象是 volatile,那对象里所有的成员也都是 volatile。其实 constvolatile 可以理解为是硬币的两面,我们经常听到看到传说中的CV修饰词就是 constvolatile 关键字。

volatile可以保证原子性吗

想必大家都知道答案,volatile 只保证内存可见性,不能保证操作是原子的,拿i++举例:

cpp 复制代码
volatile int i = 0;
i++; // i = i + 1

i++ 相当于 i=i+1,而 i=i+1 其实可以分解为好几步:

  • 先读取 i 的值到 tmp
  • 增加 tmp 的值
  • tmp 的值写回到 i 的地址里

volatile 只能保证内存可见,可以理解为上述三步中的每一步都是原子的,但是三步合起来却不一定是原子的,因为在多线程中三步中间可能插入一些其它操作改变了预期的行为,所以volatile不能用在多线程中,多线程中的原子操作还是需要使用 atomic

tips:

volatile 不能解决多线程安全问题,针对特种内存才需要使用 volatile,它和 atomic 的特点如下:

  • std::atomic 用于多线程访问的数据,且不用互斥量,用于并发编程中
  • volatile 用于读写操作不可以被优化掉的内存,用于特种内存中
相关推荐
亚历克斯神9 分钟前
智能搜索系统的升级复盘——从 Elasticsearch 到混合检索的检索质量提升
java·spring·微服务
夜不会漫长41 分钟前
C++入门(1)
开发语言·c++·算法
金銀銅鐵1 小时前
[Java] 一个方法最多可以有多少个入参?
java·jvm
哭哭啼1 小时前
JAVA服务问题诊断
java·开发语言·jvm
Sayuanni%32 小时前
SpringBoot 从注解到源码:核心知识点总结
java·spring boot·后端
坚定信念,勇往无前2 小时前
Maven 私有仓库-nexus
java
Minner-Scrapy2 小时前
Scrapy 2.17 源码解析:Scheduler 调度器与磁盘/内存双队列
java·爬虫·python·scrapy·网络爬虫·twisted
晚风醉蝶2 小时前
1-11-奇偶排序-OddEvenSort
java·数据结构·算法
旖旎夜光2 小时前
LeetCode 852:山脉数组的峰顶索引(二分查找) —— 题解
数据结构·c++·算法·leetcode·二分查找
..Dauntless..2 小时前
【C++】继承——基类和派生类的配合
开发语言·c++·算法