volatile关键字原理思想

volatile关键字原理
本篇不详细介绍原理,只是对一些容易迷惑的妨碍理解的问题加以阐述。
vloatile为什么只能保证可见性而不能保证原子性?
什么是可见性?什么又是原子性?

可见性
截止至今,由于处理器的运算速度远远大于内存io的速度,所以为了不让内存拖慢处理器进而导致处理器运算资源浪费,就在处理器里增加了高速缓存区域,这个高速缓存区域价格高,速度快,处理器利用空闲资源预先把要运算的数据从主内存中先读取到这块缓存区域,等用到时直接从缓存区域里取数据,这样就在一定程度上消除了不少处理器与主内存之间速度的鸿沟,大大增加了效率。
处理器发展到现在,都是多核心处理器,每个核心里都有一块缓存区域,而且如果是多路(多个)处理器,每个处理器又是多核,那处理器缓存区域就很多了。这些处理器都是在一个服务里处理着相同的资源,共同面对着同一块主内存,假设处理器没有缓存区域,这些处理器都直接从主内存中存取数据,那此时这些主内存里的数据相对所有的处理器核心,都是可见的,这就是可见性。一个核心直接操作了主内存中的一个数据,因为其他核心要操作这个数据时也是从主内存中相同的地址去取,所以这个数据对于所有的处理器核心都是可见的,值变化之后,其他的核心再操作这个数据,也是读取的这个值变化之后的数据,因为没有其他地方能够再读取这个数据,只能从主内存那个地址读取。如果以上不能很好理解这个可见性,那么结合接下来的 加入处理器缓存区域之后的数据存取操作 对比对比,相信大家一定能够理解什么叫做可见性。
现在讨论处理器核心里加入了缓存区域之后的对主内存中数据操作的情况。这种情况下处理器就会把要操作的数据预先读取(副本)到核心缓存区域里了,而且每个处理器核心都会把这个数据从主内存复制一份到自己核心的缓存区域,毕竟又不是只有一个核心处理那个数据,要不然还要多核多路处理器干嘛,所以每个核心都会预先把这个准备要操作的数据从主内存区域整一份到自己的核心缓存区域,以作备用。最关键的时刻要到了,当大家再对这个数据进行读取干事儿时,就不会再到主内存里去取那个数据了,而是从自己核心的缓存区域里去取来进行操作。假设一个核心从自己缓存区域里读取了这个数据,并且改变了这个数据,并把这个改变后的数据写入到了主内存,覆盖掉了主内存原来的数据,这一系列操作,其他的处理器核心一无所知!此时主内存的数据对其他的处理器核心就变得不再可见,其他的处理器核心此时还只能看见自己核心缓存区域的那个数据!这就导致了各个处理器核心缓存区域的数据不一致性(本来大家都是要操作主内存的那个数据,现在你复制到了你的缓存区域,他复制到了他的缓存区域,然后大家又互不联系,你改变了数据写回了主内存,他又改变了数据写回主内存,主内存的数据不断地被覆盖)!主内存的数据被一个核心改变了之后,其他的核心并不会再到主内存来读取,而是到自己核心的缓存区域里读取。这就造成了主内存数据对多个处理器核心的不可见!这就乱套了!所以为了解决这个问题,就出现了缓存一致性协议。
缓存一致性协议
理解了上面的缓存不一致,这个就很好说。就是某个核心从自己的缓存区域读取了某个数据并对这个数据进行了操作,然后写回主内存,此时,其他处理器核心里缓存的这个数据立即全部给我失效,并且失效之后再从主内存重新复制一份(此时主内存的这个数据已经是新的值)到自己核心的缓存区域。这就像极了处理器核心没有缓存区域时的样子。没有缓存区域时大家都是从主内存读取数据进行操作,这些数据对所有处理器核心都可见。现在有了这个缓存一致的机制,让有缓存区域的各个核心也都能读取到最新的数据了,而不是某个核心改变了某个数据,另外一个核心还傻乎乎的守着自己缓存区域里那一份数据。那么这个协议,这种机制是如何实现的呢?是如何让其中一个核心操作了数据,让其他核心缓存的这份数据都失效呢?
总线嗅探机制
处理器把运算好的数据写回主内存中是通过一条数据线路进行数据传输的,这条线路叫数据总线。处理器会监测嗅探总线上正在传输的数据,假设这个数据被某个处理器核心修改后正在向主内存传输,这个数据里是存有这个数据在主内存中的地址的,否则怎么能知道要把数据传到哪里。同时所有的处理器核心都会监测这个数据,获取到这个正在传输的数据的地址后如果发现自己的缓存区域里(同样缓存区域的数据也都带有这些数据在主内存的地址,否则假设处理器核心修改了这个数据要写回主内存不知道往哪写)也存有这份数据(地址查找对比,如果查找到自己缓存区域里也有这个地址的数据),并且发现正在传输的数据与自己存的这份不一样(被修改了,但地址没变),那么就立即将这份数据从缓存区域中抹除,彻底清理掉。然后通过数据总线再把这份数据从主内存中读取进来,此时读取进来的数据已经是被修改过的最新的值了。
volatile
volatile修饰某个变量的目的,就是为了当这个变量在数据总线上传输时,让处理器开启对这个变量数据的监测嗅探。
不能保证原子性
可以想象,当两个核心差不多同时从自己缓存区域读取某个数据(假设是整数1)到处理器寄存器中进行操作,其中一个核心对这个数据加了1并且写回主内存,此时主内存的数据变成了2(此时另外一个核心的缓存区域的这个数据的值也变为了2),而另一个核心在这之间失去了处理执行权,当主内存的这个数据被其他核心整成3时,这个核心重获执行权,此时这个核心手里的数据(寄存器中,注意非缓存区域)还是1,进行加1操作并写回主内存,主内存的数据就从3变成了2。不能保证一个整数相加的方法始终是结果逐渐变大的。原子操作就是在对某个数据或某些数据操作的过程不能被打断的操作,像那种还没操作完就失去执行权的操作就不是原子操作。
以上描述只是一种思想逻辑上的描述,并不代表具体的实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值