首页 > 编程语言 >C++ volatile

C++ volatile

时间:2024-03-19 19:44:05浏览次数:22  
标签:const 变量 C++ 关键字 线程 内存 volatile

1. volatile关键字

C++ 中的 volatile 关键字和 const 对应,用来修饰变量,通常用于建立语言级别的 memory barrie

volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。

遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问

声明时语法:int volatile vInt; 当要求使用 volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。

2. volatile 指针

和 const 修饰词类似,const 有常量指针和指针常量的说法,volatile 也有相应的概念:

  • 修饰由指针指向的对象、数据是 const 或 volatile 的:
    const char* cpch;
    volatile char* vpch;
    
  • 指针自身的值——一个代表地址的整数变量,是 const 或 volatile 的:
    char* const pchc;
    char* volatile pchv;
    

注意:

  • 可以把一个非volatile int赋给volatile int,但是不能把非volatile对象赋给一个volatile对象

  • 除了基本类型外,对用户定义类型也可以用volatile类型进行修饰。

  • C++中一个有volatile标识符的类只能访问它接口的子集,一个由类的实现者控制的子集。用户只能用const_cast来获得对类型接口的完全访问。

此外,volatile向const一样会从类传递到它的成员。

3. 多线程下的volatile

有些变量是用volatile关键字声明的。当两个线程都要用到某一个变量且该变量的值会被改变时,应该用volatile声明,该关键字的作用是防止优化编译器把变量从内存装入CPU寄存器中。

如果变量被装入寄存器,那么两个线程有可能一个使用内存中的变量,一个使用寄存器中的变量,这会造成程序的错误执行。

volatile的意思是让编译器每次操作该变量时一定要从内存中真正取出,而不是使用已经存在寄存器中的值。

4. volatile内存屏障

  1. volatile如何通过内存屏障保证可见性与有序性?
  • volatile修饰的变量,在每个读操作(load操作)之前都加上Load屏障,强制从主内存读取最新的数据。每次在assign赋值后面,加上Store屏障,强制将数据刷新到主内存。

  • 其实说白了就是通过一个屏障让volatile的变量每次读都读主存,每次修改后立即刷到主存里面。

  • 好比线程A修改 i立即将值刷到主存里面,后面线程B用到的时候强制从主存读取,这个时候它能看到的值是线程A修改之后的值了。也就是通过这种方式来保证多线程之间的可见性吧。

  1. volatile为什么保证不了原子性?
  • 线程A执行 i++ 结果后将 i = 1 赋值给工作内存;但是这个时候还没来的将最新的结果刷新回主内存的时候,线程B就使用读取主内存的旧值 i = 0 ,然后执行use指令将 i = 0的值传递给线程B去进行操作了。

  • 即使这个时候线程A立即将 i = 1刷入主内存,那也晚了;线程B已经使用旧值 i = 0进行操作了,像这种情况计算结果就不对了。

标签:const,变量,C++,关键字,线程,内存,volatile
From: https://www.cnblogs.com/love-9/p/18083784

相关文章

  • C++ static
    1.隐藏(static函数,static变量均可)当同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。如果加了static,就会对其它源文件隐藏。利用这一特性可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。static可以用作函数和变量的前缀,对于函数来讲,sta......
  • C++高级面试题:解释 C++ 中的函数对象适配器
    解释C++中的函数对象适配器函数对象适配器是C++中的一种编程技术,用于修改或增强现有的函数对象的行为。它们通常通过组合或包装现有的函数对象来实现所需的功能。函数对象适配器允许我们在不修改原始函数对象的情况下,对其进行修改或扩展。这样可以实现代码的重用和可......
  • C++ static和const
    const定义的常量在超出其作用域之后其空间会被释放;static定义的静态常量在函数执行后不会释放其存储空间;1.staticstatic表示的是静态的。类的静态成员函数、静态成员变量是和类相关的,而不是和类的具体对象相关的。即使没有具体对象,也能调用类的静态成员函数和成员......
  • const,static深度总结——c++穿透式分析
         前言;c++类和对象的知识点中除了几种默认函数,比较重要的还有使用const和static修饰成员相关知识点。const在c++中特性很简单。但是在使用中,比较容易疏忽大意出现问题。static特性也很简单,但是比起const来要直接的多。在使用中只要熟练语法以及底层原理。就......
  • C++ memcpy、memmove
    函数原型:void*memcpy(void*dest,constvoid*src,size_tcount);void*memmove(void*dest,constvoid*src,size_tcount);memcpy和memmove相同点:都是用于从src拷贝count个字节到destmemcpy和memmove区别:如果目标区域和源区域有重叠的话:memcpy不能够确保源......
  • c++学习记录 STL—常用查找算法
    一、算法简介find               //查找元素find_if             //按条件查找元素adjacent_find       //查找相邻重复元素binary_search      //二分查找法count        ......
  • C++ kmalloc、kzalloc、vmalloc的区别
    1.kmalloc函数原型:void*kmalloc(size_tsize,gfp_tflags);kmalloc()申请的内存位于物理内存映射区域,而且在物理上也是连续的,它们与真实的物理地址只有一个固定的偏移,因为存在较简单的转换关系,所以对申请的内存大小有限制,不能超过128KB。较常用的flags(分配内存的方法):G......
  • 高质量C/C++编程指南
    目录        1、概述    本文档参考《高质量C++C编程指南》及自己的心得编写,如有侵权,立刻删除!2、编程指南2.1文章结构    每个C++/C程序通常分为两个文件。一个文件用于保存程序的声明,我们称之为头文件。另一个文件用于保存程序的实现,我们称......
  • c++线程池(二)——线程池优化
    文章目录概要整体架构流程技术细节小结概要增加扇入扇出:优化:子线程维护自己的本地队列分析:目前文章《线程池一》介绍了一个简单的线程池,存在多个线程同时访问一个任务队列Task,出现抢锁的情况,这样会存在一定的性能消耗,会导致有些没抢到任务的线程没事做,造成资源浪......
  • 06_C++多维数组
    多维数组,数组指针在二维数组上的应用。#include<iostream>#include<stdio.h>usingnamespacestd;intmain(){intarr[3][5]={{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15}};int(*p)[5]=arr;cout<<"*p:"<<*p<<endl......