首页 > 其他分享 >C语言中关键字volatile

C语言中关键字volatile

时间:2024-07-13 17:28:02浏览次数:12  
标签:变量 C语言 关键字 线程 内存 volatile 多线程 读取

 1:什么是volatile?

       在C语言中,volatile关键字同样用于修饰变量,volatile告诉编译器该变量的值可能会在程序的控制之外被改变,因此编译器在优化代码时不能对该变量的访问进行优化,比如不能将其缓存到寄存器中,而是每次访问时都需要直接从内存中读取其值。

2:变量的访问原理。

1,读变量;

内存->寄存器(CPU)

2,写变量;

寄存器(CPU)->内存

正常变量的访问应该是这个样子;

但是在计算机工作时,内存的访问速度不及CPU的处理速度,为了提升计算机的整体性能,在软硬件层面都有相应的优化机制。

1,硬件层面

引入高速缓冲(cache)。

2,软件层面

(1)编码优化(程序员)。

(2)编译优化(编译器)。

3:volatile的作用。

        volatie的意思是“易变的”,在C语言中使用volatile修饰一个变量时,表示这个变量的值随时都有可能发生改变。因此编译器在编译的时候对该变量的存取操作不能进行优化,即告诉编译器每次存取该变量的时候都要从内存中去存取而不是使用之前在寄存器中的备份。

C语言中volatile的主要用途包括:

  1. 内存映射的硬件寄存器:在嵌入式系统或系统编程中,经常需要通过C语言直接访问硬件寄存器。这些寄存器的值可能会由硬件事件(如中断,ADC采集等)或其他并发运行的程序部分意外地改变。在这种情况下,使用volatile可以确保每次访问寄存器时都能从硬件地址中读取最新的值,而不是从可能被编译器缓存的旧值中读取。

  2. 多线程环境中的共享变量:虽然C语言标准本身并不直接支持多线程(这是由操作系统或第三方库提供的),但在多线程程序中,使用volatile可以确保一个线程对共享变量的修改能够立即对其他线程可见。然而,volatile并不保证操作的原子性,也不提供互斥访问,因此在多线程程序中通常需要与适当的同步机制(如互斥锁)结合使用。

  3. 信号处理器中的变量:在C语言中,可以使用信号处理器来响应硬件或软件事件(如中断)。在信号处理器中访问的变量应该被声明为volatile,因为信号处理器可能在主程序的执行流之外被调用,从而改变这些变量的值。

4:使用volatile关键字的优缺点

优点

  1. 保证可见性

           当一个线程修改了volatile变量的值,这个新值对其他线程来说是立即可见的。这是通过禁止指令重排序和立即刷新到主内存中实现的。这避免了在多线程环境下,一个线程修改了共享变量的值,而另一个线程却读取不到最新值的问题。                                                                       具体来说,当一个线程修改了volatile变量的值时,该线程会将该变量的值立即写入主内存中,并通知其他线程该变量已经发生了修改。其他线程在读取该volatile变量时,会从主内存中重新读取最新的值,而不是从本地工作内存中读取。
  2. 保证有序性

                volatile关键字可以禁止指令重排序,从而保证对volatile变量的操作是有序的。当对一个volatile变量进行读/写操作时,该操作之前的代码必须已经执行完成,并且结果对后续的操作可见。这有助于避免多线程环境下可能出现的因指令重排序而导致的错误。
  3. 轻量级同步

           相对于其他同步机制(如synchronized),volatile是一种轻量级的同步机制。它不需要通过锁机制来同步对共享变量的访问,从而减少了因锁竞争而导致的性能开销。

缺点

  1. 不保证原子性

            虽然volatile可以保证对变量的操作具有可见性和有序性,但它并不能保证操作的原子性。例如,对于i++这样的操作,它实际上包含了读取、修改和写入三个步骤,而volatile只能保证这三个步骤的可见性和有序性,但不能保证它们作为一个整体是原子的。因此,在多线程环境下,如果需要对变量进行复合操作(如自增、自减等),仅使用volatile是不够的,还需要使用其他同步机制(如synchronized或原子类)来保证操作的原子性。                                    (**原子性(Atomicity)**是指一个或多个操作要么全部执行成功,要么全部执行失败,在执行过程中不会被任何因素打断的特性。在并发编程中,原子性是一个非常重要的概念,它用于保证多线程环境下对共享数据的访问是安全的。)
  2. 性能开销

             虽然volatile相对于其他同步机制来说是一种轻量级的同步方式,但它仍然会对性能产生一定的影响。这是因为volatile变量在每次被线程访问时,都需要从主内存中读取最新的值,并且在修改后需要将新值写回主内存。这种频繁的内存访问操作会增加CPU的缓存一致性开销和内存带宽消耗。
  3. 使用限制

             volatile的使用场景相对有限。它主要适用于那些被多个线程读取,但只有一个线程写入(或者写入操作不依赖于当前值)的共享变量。如果变量的写入操作依赖于其当前值,或者多个线程同时写入同一个变量,那么仅使用volatile是不够的,还需要结合其他同步机制来保证线程安全。

标签:变量,C语言,关键字,线程,内存,volatile,多线程,读取
From: https://blog.csdn.net/m0_67669662/article/details/140396467

相关文章

  • Java中标识符和关键字
    1.标识符publicclassHelloWorld{publicstaticvoidmain(String[]args){System.out.println("Hello,world");}}上述代码中在publicclass后面的HelloWorld称为类名,main称为方法名,也可以将其称为标识符,即:在程序中由用户给类名、方法名或者变量所取的名字。【......
  • C语言——数组、sizeof关键字
    一、数组1.数组的引入与定义: C语言中的数组是一种基本的数据结构,用于在计算机内存中连续存储相同类型的数据。数组中的每个元素可以通过索引来访问,索引通常是一个整数,用于指定元素在数组中的位置。在C语言中,数组索引是从0开始的。 要使用数组,必须在程序中先定义数组,即通知......
  • const关键字
    目的:是一种机制可以让代码更加干净,用来规范开发人员有点类似可见性的概念。写法1constint*a=newint;//修饰的inta表面不能修改解引用的内容intb=1;constinta=&b;a=7//会报错;写法2intconsta=newint;//不能修改指向的地址;intc=0;a=&0;//会报错写法3constint......
  • 帝国CMS网站系统内置关键字字段说明
    1、newstext:内容字段newstext字段为自动就是编辑器,一般用于新闻内容字段。支持内容关键字替换、替换过滤字符、支持远程保存内容里的图片/FLASH、支持自动分页、支持设置第几张上传图为标题图片。2、smalltext:简介字段smalltext字段一般用于简介内容,可自动截取newstext字......
  • C语言内存管理深度解析
    第一章基础概念梳理1.1堆与栈的区别在C语言中,堆和栈是两种重要的内存管理机制,它们之间存在显著的区别。首先,栈内存是由编译器自动分配和释放的,其操作方式类似于数据结构中的栈,遵循后进先出(LIFO)的原则。每当一个函数调用发生时,就会在栈上分配一块内存用于存储该函数的局部变......
  • C语言菜鸟学习(函数)
    引入C语言本身就是由多个函数模块组成,在C语言本身自带的头文件中,也有很多被封装好的函数,在初学C语言时,我们最先使用的就是使用printf()函数输出一个“helloworld”;而printf()函数就是被封装在#include<stdio.h>头文件中的。但是经过封装的函数我们无法看到源代码,在实际开发中......
  • C语言——练习:水仙花数、n次幂值的计算
    1.输入一个数判断是否是水仙花数,并输出100—999之间所有的水仙花数水仙花数(Narcissisticnumber),也被称为超完全数字不变数(pluperfectdigitalinvariant,PPDI)、自恋数、自幂数、阿姆斯壮数或阿姆斯特朗数(Armstrongnumber),是指一个N位正整数(N≥3),它的每个位上的数字的N次幂之和......
  • 在VSCODE中创建C语言环境,编译、运行、调试。
    1、安装MinGWMinGW-w64-for32and64bitWindowsdownload|SourceForge.net下载下来是一个压缩包对压缩包解压得到文件夹mingw64将文件夹mingw64剪切到C:\ProgramFiles目录下配置环境变量点击系统变量里面的Path将C:\ProgramFiles\mingw64\bin目录添加......
  • Java基础之——final关键字的使用
    #Java基础复习##参考文章:Java:final关键字的作用(方法、变量、类)_java语言中在类定义时使用final关键字修饰是指这个类-CSDN博客#一、理解含义final是Java中一个保留的关键字,可以用于修饰变量、方法和类。任何实体(变量,方法或类)一旦被声明final后,只能分配(赋值)一次。也就是......
  • 【C语言】字符串与相关操作函数
    字符串思路分析在注释文章目录字符串一、字符串的定义1.使用sizeof()计算他们的长度二、sizeof和strlen的区别1.sizeof操作符2.strlen函数三、动态开辟字符串1.malloc函数2.realloc函数3.free函数4.memset函数四、几种字符串常用的API1.strncpy函数2.asse......