volatile详解

volatile关键字确保在多线程环境下共享变量的可见性和有序性。它涉及到CPU缓存一致性问题,如MESI协议和总线嗅探机制。当一个CPU修改volatile变量时,会通知其他CPU更新缓存,避免数据不一致。此外,volatile还阻止指令重排序,保证特定操作的顺序。
摘要由CSDN通过智能技术生成

volatile详解

volatile的作用?

volatile关键字能够保证在多线程下共享变量可见性和程序的有序性.

原理:

首先,先介绍一下CPU多级缓存模型,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传在这里插入图片描述

为了降低CPU和内存速度上的差异,引入了多级缓存来暂存要处理的数据,当CPU要处理数据时,会首先去缓存中取,如果缓存中没有的话,才会去内存中查询。

当CPU对缓存中的数据进行修改以后,会将缓存中的数据刷新到内存中。

但是因为引入了缓存,也就导致了问题的发生(缓存一致性问题):

  1. CPU1读取数据a=1,CPU1的缓存中都有数据a的副本
  2. CPU2也执行读取操作,同样CPU2也有数据a=1的副本
  3. CPU1修改数据a=2,同时CPU1的缓存以及主内存a=2
  4. CPU2再次读取a,但是CPU2在缓存中命中数据,此时a=1

缓存一致性协议:

为了解决这个问题,早期是通过在总线上直接加锁的形式来解决缓存不一致的问题,但是直接加锁导致其他CPU不能访问,效率低下。后面出现了缓存一致性协议:

MESI协议:

有四种状态:

M: 当一个CPU的缓存行中的数据被修改了,该数据就会被修改为M状态

E: 当一个数据只被一个缓存所使用,该缓存行被置为E

S: 当多个CPU也读取了该数据到缓存中时,所有持有该数据的缓存行被置为S

I: 当一个CPU修改了数据被置为M,其他的缓存行会被置为I。

核心思想就是:当CPU对一个数据进行修改的时候,发现操作的变量是共享变量(发现其他CPU的缓存中也存有这个数据的副本),会通知其他CPU将该缓存行置为无效状态(I),当CPU去查询缓存时,发现某个缓存行的状态时无效状态时,会将这个缓存行丢弃,然后去内存中读取。

总线嗅探机制:

CPU对缓存行的监听和通知就是基于总线嗅探机制来实现的。

嗅探机制其实就是一个监听器,如果是加入MESI缓存一致性协议和总线嗅探机制之后:

  1. CPU1读取数据a=1,并同步缓存,并将缓存中的该缓存行设置为E
  2. 当CPU2读取数据a=2,总线嗅探机制发现CPU1中的缓存中也有a的副本,于是这些缓存行设置为S状态
  3. 当CPU1对数据进行修改时a=2,并将数据刷新到内存中,并且发现CPU1中缓存行的状态时S,此时总线嗅探机制会将其他CPU中缓存状态设置为I。
  4. 当CPU2去缓存中读取数据进行操作时,发现该数据的副本的状态为I,于是将该数据丢弃,然后去内存中重新读取并更新缓存。

当我们使用volatile关键字修饰某个变量之后,就相当于告诉CPU:我这个变量需要使用MESI和总线嗅探机制处理。从而也就保证了可见性。

指令重排序:

再加入MESI和总线嗅探机制后,当CPU2去内存中重新取值时,但是CPU1将数据刷新到内存中是需要时间的,如果读取的时候,CPU

总线嗅探机制后,当CPU2去内存中重新取值时,但是CPU1将数据刷新到内存中是需要时间的,如果读取的时候,CPU

1还没有将数据刷新完成,CPU2不会傻傻等着,会先处理后面的逻辑(前提是交换顺序不会影响程序的结果)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值