C语言volatile的作用及使用场景介绍

简介

volatile
先从基础的知识说起吧,这样也有个来龙去脉。

我们都知道,程序运行后,程序的数据都会被从磁盘加载到内存里面(主存)

而当局部的指令被执行的时候,内存中的数据会被加载到更加靠近CPU的各级缓存,以及寄存器中

 

 

一、多线程多核机器的全局变量

当一个多线程程序执行在一个多核心的机器上时,就会出现真正的并行情况,每个线程都独立的运行在一个CPU上,每个CPU都有属于自己独立的周边缓存

那么此时,一个变量被两个线程操作,从内存复制到CPU缓存时,就可能出现两份了,这个时候就会出现问题,比如说简单的自增操作,就会变成,你加你的,我加我的,这样运行的效果就会偏离预期。线程1在CPU1上只看得见自己的缓存变量,线程2在CPU2上,也只看得见自己的缓存变量,它们都认为这是正确的、唯一的变量。这样也就导致程序运行结果偏离了预期

volatile关键字就是用来处理这种可见性的问题

当一个变量被标记为volatile的时候,这个变量将被放在主存里面,而不是CPU的缓存里面。当这个变量被读取的时候,是从主存读取,当这个变量被写入的时候,是写入到内存。

二、读写速度

总所周知,内存肯定是比CPU缓存的读写速度要慢的。
那,是不是就意味着读写volatile的变量,效率会比非volatile的变量低呢。

为了验证这个问题,我写了一个简单的程序,分别有3个变量,分别是成员变量,volatile修饰的成员变量,和static静态变量。

对它们进行1000000000次自增,然后记录下完成时间。

以上的操作执行10次,取平均值。

最终得到了以下的结果:

avg-------------- 
normal: 32.4 
volatile: 5828.3 
static: 43.8 

看来读写volatile变量,确实要比普通的变量要慢,但也是数量级非常大的时候,才会非常明显。

下面是我做的实验,右边比左边逐渐少一个量级,相对于数量级增长,volatile关键字修饰的变量读写耗时有了等比的线性增长。

普通的成员变量和静态变量就没有这样的现象了,可见CPU缓存对性能的巨大提升。

三、竞争问题

那么,使用volatile关键字可以让变量总是读写于内存,是不是就可以用它来避免多线程读写同一个变量导致的竞争问题呢?
答案是不能

因为,volatile关键字只是保证变量的可见性,而没有保证操作的原子性,因此,只使用这个关键字无法保证操作的原子性

四、volatile的应用场景

这个问题,我也是查了非常多的资料,花了几天的时间才搞清楚一点点。

正确的使用场景,基本符合一个原则:一写多读:有一个数据,只由一个线程更新,其他线程都来读取

五、总结

  1. volatile的作用是很微妙的,它并不能替代synchronized,因此它无法提供同步的能力,它只能提供改变可见性的能力 (可见性:多个线程访问同一个变量时,这个变量被修改后,能被其他的线程看到。)。

  2. 由于总是读写与主存,它的读写性能要低于普通的变量。

  3. 正确使用的模式总结下来就是一个线程写,多个线程读。

  4. 单片机存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义.
    主要在硬件驱动编写volatile的作用: 作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值.

简单地说就是防止编译器对代码进行优化.比如如下程序:

XBYTE[2]=0x55;
XBYTE[2]=0x56;
XBYTE[2]=0x57;
XBYTE[2]=0x58;

对外部硬件而言,上述四条语句分别表示不同的操作,会产生四种不同的动作,但是编译器就不能像对待纯粹的程序那样对上述四条语句进行优化,只认为XBYTE[2]=0x58(即无volatile则忽略前三条语句,只产生一条机器代码)。如果键入volatile,则编译器会逐一的进行编译并产生相应的机器代码(四条).

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值