Cpp关键字破解(三)【volatile】篇

2023-11-18

关键字总结-volatile

0 - 前言

参考几位前辈博客,汇总整理了一下

C++中volatile关键字的使用详解

详解C/C++中volatile关键字

详解volatile在C++中的作用


1 - 概念

了解volatile关键字之前,需要了解:一个变量被编译器编译时,会在寄存器上创建一个副本(这一步叫优化,因为CPU访问寄存器的速度要快过RAM,相当于加快了程序访问这个变量的速度)。

随机存取存储器(Random Access Memory,RAM),也叫主存,是与CPU直接交换数据的内部存储器。它可以随时读写(刷新时除外),而且速度很快,通常作为操作系统或其他正在运行中的程序的临时数据存储介质。RAM工作时可以随时从任何一个指定的地址写入(存入)或读出(取出)信息。它与ROM的最大区别是数据的易失性,即一旦断电所存储的数据将随之丢失。RAM在计算机和数字系统中用来暂时存储程序、数据和中间结果。

volatile给编译器的指示:对它所修饰的对象不应该执行优化。volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。


2 - 作用

volatile的作用就是用来进行多线程编程。

如果一个基本变量被volatile修饰,编译器将不会把它保存到寄存器中,而是每一次都去访问内存中实际保存该变量的位置上。这一点就避免了 没有volatile修饰的变量在多线程的读写中所产生的由于编译器优化所导致的灾难性问题。所以多线程中必须要共享的基本变量一定要加上volatile修饰符。当然了,volatile还能让你在编译时期捕捉到非线程安全的代码。

class Student { 
public: 
    void Wait() { 
    while(!flag) { 
        Sleep(1000); // sleeps for 1000 milliseconds 
    } 
} 
    void eat() { 
        flag = true; 
    } 
    ... 
private: 
    bool flag = false; 
};

上面程序的本意是:当调用eat()函数时,将开饭标志flag置为true,但是在编译时,编译器会优化flag变量,在寄存器创建相同的副本。此时,在多线程中,另一个线程启用了开饭标志(将flag置为true),但是寄存器中的副本并未改变,就导致原来地址上的“真”开饭标志flag被忽略掉了。所以,这个开饭标志需要修改为:volatile bool flag = false;

如果变量加上volatile修饰,则编译器保证对此变量的读写操作都不会被优化(肯定执行)


3 - 使用场景

1、中断服务程序中修改的供其它程序检测的变量需要加volatile;
2、多任务环境下各任务间共享的标志应该加volatile;
3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;


4 - volatile成员函数

关于类的话,首先如果类是volatile则里面的成员都是volatile的。

其次要将成员函数声明为volatile则同const一样在函数最后声明即可。

当你设计一个类的时候,你声明的那些volatile成员函数是线程安全的,所以那些随时可能被调用的函数应该声明为volatile。

考虑到volatile等于线程安全代码和非临界区;non-volatile等于单线程场景和在临界区之中。我们可以利用这个做一个函数的volatile的重载来在线程安全和速度优先中做一个取舍。


5 - 代码体验

#include <stdio.h>
 
void main()
{
	int i = 10;
	int a = i;
	
	printf("i = %d", a);
 
	// 下面汇编语句的作用就是改变内存中 i 的值
	// 但是又不让编译器知道
	__asm{
		mov dword ptr [ebp-4], 20h
	}
	 
	int b = i;
	printf("i = %d", b);
}

在 Debug 版本模式运行程序,输出结果如下:

i = 10
i = 32

在 Release 版本模式运行程序,输出结果如下:

i = 10
i = 10

输出的结果明显表明,Release 模式下,编译器对代码进行了优化,第二次没有输出正确的 i 值。下面,我们把 i 的声明加上 volatile 关键字,看看有什么变化:

#include <stdio.h>
 
void main()
{
	volatile int i = 10;
	int a = i;
 
	printf("i = %d", a);
	__asm {
		mov dword ptr [ebp-4], 20h
	}
	
	int b = i;
	printf("i = %d", b);
}

分别在 Debug 和 Release 版本运行程序,输出都是:

i = 10
i = 32

这说明这个 volatile 关键字发挥了它的作用。其实不只是“内嵌汇编操纵栈”这种方式属于编译无法识别的变量改变,另外更多的可能是多线程并发访问共享变量时,一个线程改变了变量的值,怎样让改变后的值对其它线程 visible。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Cpp关键字破解(三)【volatile】篇 的相关文章

  • IEnumerable 的 String.Join(string, string[]) 的类似物

    class String包含非常有用的方法 String Join string string 它从数组创建一个字符串 用给定的符号分隔数组的每个元素 但一般来说 它不会在最后一个元素之后添加分隔符 我将它用于 ASP NET 编码 以用
  • 锁定 ASP.NET 应用程序变量

    我在 ASP NET 应用程序中使用第三方 Web 服务 对第 3 方 Web 服务的调用必须同步 但 ASP NET 显然是多线程的 并且可能会发出多个页面请求 从而导致对第 3 方 Web 服务的同时调用 对 Web 服务的调用封装在自
  • C free() 是如何工作的? [复制]

    这个问题在这里已经有答案了 可能的重复 malloc 和 free 如何工作 https stackoverflow com questions 1119134 how malloc and free work include
  • MFC CList 支持复制分配吗?

    我在 MSVC 中查找了 CList 定义afxtempl h http www cppdoc com example mfc classdoc MFC AFXTEMPL H html并记录在MSDN http msdn microsoft
  • 司机和提供商之间的区别

    数据库中的驱动程序和提供程序有什么区别 有没有解释一下 不胜感激 样本 ADO NET driver for MySQL vs providerName System Data EntityClient 来自 MSDN 论坛 驱动程序是安装
  • 为什么需要数字后缀?

    C 语言 我确信还有其他语言 需要在数字文字末尾添加后缀 这些后缀指示文字的类型 例如 5m是一个小数 5f是一个浮点数 我的问题是 这些后缀真的有必要吗 或者是否可以从上下文中推断出文字的类型 例如 代码decimal d 5 0应该推断
  • C# 编译器数字文字

    有谁知道 C 编译器数字文字修饰符的完整列表 默认情况下 声明 0 使其成为 Int32 声明 0 0 使其成为 Double 我可以在末尾使用文字修饰符 f 来确保某些内容被视为 Single 例如像这样 var x 0 x is Int
  • 在 C++11 中移出 stdpriority_queue 的元素

    最小的工作示例 include
  • 如何在win32中使用GetSaveFileName保存文件?

    我编写此代码是为了获取 fileName 来保存我的文件 include stdafx h include
  • 通过 C# Mailkit / Mimekit 发送电子邮件,但出现服务器证书错误

    Visual Studio 2015 中的 0 代码 1 我正在使用 Mailkit 最新版本 1 18 1 1 从我自己的电子邮件服务器发送电子邮件 2 电子邮件服务器具有不受信任的自签名证书 3 我在代码中添加了以下两行 以忽略服务器证
  • 子目录中的头文件(例如 gtk/gtk.h 与 gtk-2.0/gtk/gtk.h)

    我正在尝试使用 GTK 构建一个 hello world 其中包括以下行 include
  • C++ 到 C# 事件处理

    所以我有我的C WinForm 应用程序 我从中调用我的C CLI MFC dll图书馆 但也有一些events在我的 C 库上 甚至此事件也发生在该库的本机 非 CLI 部分 我需要从我的 C 应用程序调用一些代码 并获取一些有关此事件的
  • 无法在 C# 中为 EventArgs 分配使用派生类型的事件处理程序

    所以我有一个事件声明如下 public event EventHandler OnChangeDetected 然后我有以下处理程序被分配给该事件 myObject OnChangeDetected OnTableChanged 我的理解是
  • 浮点字节序?

    我正在为实时海上模拟器编写客户端和服务器 并且由于我必须通过套接字发送大量数据 因此我使用二进制数据来最大化可以发送的数据量 我已经了解整数字节顺序以及如何使用htonl and ntohl为了规避字节顺序问题 但我的应用程序与几乎所有模拟
  • Linq.Select() 中的嵌套表达式方法调用

    I use Select i gt new T 每次手动点击数据库后将我的实体对象转换为 DTO 对象 以下是一些示例实体和 DTOS 用户实体 public partial class User public int Id get set
  • Xamarin.Forms UWP 项目中标题栏和选项卡之间令人恼火的空白

    我几乎是新手Xamarin Forms我正在开发一个相当简单的跨平台应用程序 该应用程序在 Android 中显示得足够好 但在 UWP 中却出现了一个愚蠢的空白 该项目由一个 TabbedPage 组成 其中包含 4 个 Navigati
  • “必须声明标量变量”错误[重复]

    这个问题在这里已经有答案了 必须声明标量变量 Id SqlConnection con new SqlConnection connectionstring con Open SqlCommand cmd new SqlCommand cm
  • printf或iostream如何指定点后的最大位数

    字符串采用什么格式printf or iomanip我应该使用 iostream 中的运算符以以下格式打印浮点数 125 0 gt 125 125 1 gt 125 1 125 12312 gt 125 12 1 12345 gt 1 12
  • 这种尺寸对齐是如何工作的

    对于所提供的评论 我无法理解以下代码 这段代码的作用是什么 以及等效的代码是什么8 aligned segment size must be 4 aligned attr gt options ssize 3 Here ssize is o
  • C++ Boost ASIO 简单的周期性定时器?

    我想要一个非常简单的周期性计时器每 50 毫秒调用我的代码 我可以创建一个始终休眠 50 毫秒的线程 但这很痛苦 我可以开始研究用于制作计时器的 Linux API 但它不可移植 I d like使用升压 我只是不确定这是否可能 boost

随机推荐

  • 强化学习笔记(1)-同策回合更新算法

    在我上一篇博客文章https blog csdn net gzroy article details 119509552中对21点的策略进行了研究 采用蒙特卡洛的方式来进行多次的模拟 通过对比不同策略的收益来找到最佳的策略 主要是通过概率的
  • layui的分页实例详解

    原 layui的分页实例详解 2018年09月20日 17 43 07 李什么泽 阅读数 11571 更多 分类专栏 layui分页 版权声明 本文为博主原创文章 遵循 CC 4 0 BY SA 版权协议 转载请附上原文出处链接和本声明 本
  • ndk错误总结

    1 ndk Unresolved inclusion
  • mongo在linux下的安装(实践记录)

    1 下载安装包 wget http fastdl mongodb org linux mongodb linux i686 1 8 2 tgz 下载完成后解压缩压缩包 tar zxf mongodb linux i686 1 8 2 tgz
  • IDEA Cannot resolve plugin org.apache.maven.pluginsmaven-jar-plugin2.4

    起因 最近在弄Maven项目 在使用IDEA创建Maven项目得时候一直报错 搞的我很头疼 网上搜索答案 都是修改Setting xml 配置本地仓库 然后我测试了好多次都不管用 但是根据错误信息他的确是Maven仓库配置得问题和IDEA
  • 初识GoogleTest

    1 初识GoogleTest 首先要了解googletest是做什么的 主要是单元测试框架 第二是googletest有什么优势 测试过程独立可以重复 测试组织与代码结构保持比较好的一致性 支持跨平台 失败后能够提供完整错误信息 同时支持失
  • 来谈谈 BlockingQueue 阻塞队列实现类 java.util.concurrent.LinkedBlockingQueue(JDK1.8 源码分析)

    LinkedBlockingQueue源码刨析 文章目录 LinkedBlockingQueue源码刨析 前言 一 LinkedBlockingQueue源码部分 1 构造方法 2 成员变量 3 主要方法 1 入队操作 offer方法 pu
  • 毕设草稿保存

    这里写目录标题 参数大小 MobileViT xxs参数 MobileViT xs参数 MobileViT s参数 MobileViT SE模块 无SE模块时 有预训练文件 无预训练文件 有预训练文件且加SE模块之后 无预训练文件且加了SE
  • 【数据结构】——八大排序

    文章目录 1 插入排序 2 冒泡排序 3 希尔排序 4 选择排序 5 快速排序 快排优化 递归改非递归 6 堆排序 7 归并排序 递归归并排序 改成非递归 8 计数排序 9 题目 总结 排序的时间检验 对于不同排序的时间复杂度分析 1 插入
  • 大模型PEFT技术原理(三):Adapter Tuning及其变体

    随着预训练模型的参数越来越大 尤其是175B参数大小的GPT3发布以来 让很多中小公司和个人研究员对于大模型的全量微调望而却步 近年来研究者们提出了各种各样的参数高效迁移学习方法 Parameter efficient Transfer L
  • [Centos] 如何查看linux系统架构(amd64、arm、arm64

    这几天搭建一个基于扣扣的聊天机器人项目时总会无法运行 试想是架构选错了 一直在网上收集查看架构的详细方法 上链接 https www cnblogs com liyuanhong articles 4859816 html
  • 用python实现PyEcharts中的条形图,直方图

    用python实现PyEcharts中的条形图 直方图 笔记仅是个人的学习笔记总结 如有雷同请见谅 条形图 1 普通使用 from pyecharts charts import Bar 引用Faker来生成数据 from pyechart
  • IOS编程教程(十一):在故事板联线(Segue)中的不同视图控制器里传值

    这是我们演示故事板系列的第二篇文章 在前一个教程中 我们介绍了故事板 那是一个在Xcode中方便设计友好用户界面的功能 如果你跟着教程走 从开始到现在 你应该已经建立了一个简单的菜单应用程序的导航界面 但是上一篇我们有一件事没讨论 那就是如
  • table.getn(tableName) 的用法注意。

    转自 http blog sina com cn s blog 4a2e9af90100cv1z html 1 table getn tableName 等同于操作符 作用 得到一个table的大小 注意 该table的key必须是有序的
  • 启航2021

    1 企业数字化升级之路 附下载地址 点击标题 快速进入下载页面 近年来创新技术的不断升级迭代和突如其来的新冠疫情对各 各业数字化转型的推动 让企业管理者普遍认同数字化 智能化的企业运营模式 能够有效助 企业抗击 险 提升效能 获得 远发展
  • matlab-knn使用

    play with knn 1 什么是knn 1 1 什么是knn 1 2 knn适用范围 2 knn实验前的准备 2 1 knn的实验要点 3 knn的matlab实验 使用UCI数据集 3 0 KNN函数自带用例 3 1 UCI数据集
  • 3.docker仓库(Nexus、Harbor)的安装

    本文目录 前言 1 Aliyun 镜像仓库 2 Nexus 1 Nexus 私服搭建 2 登录控制台 3 配置nexus仓库 4 配置nexus仓库地址为安全的镜像地址 5 镜像推送至nexus仓库 6 拉取nexus仓库镜像 3 Harb
  • c++顺序表与链表的区别

    C Lists 链表 Lists将元素按顺序储存在链表中 与 向量 vectors 相比 它允许快速的插入和删除 但是随机访问却比较慢 说起这个访问速率呢 给大家举个很简单的例子 向量 vectors 也就是顺序表 它的存储方法就类似于c语
  • Exception in thread "main" java.lang.NoClassDefFoundError: XXX

    Exception in thread main java lang NoClassDefFoundError XXX编译时没有报错 一运行就不听话网上找了一大堆 各种解决方案都不是适合我 但是一片文章列举出了可能产生的原因https bl
  • Cpp关键字破解(三)【volatile】篇

    关键字总结 volatile 文章目录 关键字总结 volatile 0 前言 1 概念 2 作用 3 使用场景 4 volatile成员函数 5 代码体验 0 前言 参考几位前辈博客 汇总整理了一下 C 中volatile关键字的使用详解