Volatile

什么是Volatile?

Java语言机制提供了一种稍弱的同步机制,即Volatile变量,用来确保将变量的更新操作通知到其他线程,当把变量声明为Volatile后,编译器会注意到这个变量是共享的,因此不会把对该变量的操作与其他内存操作一起重排序。Volatile变量不会被缓存在寄存器或对其他处理器不可见的地方,因此读取Volatile类型的变量总会返回最新写入的值

 

volatile的两层含义?

可见性,禁止重排序

 

volatile的内存屏障?

   loadstore    loadload    storestore    storeload

 

Volatile的好处?

在访问Volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,所以Volatile是一种比Synchronized更加轻量级的同步机制。Volatile变量对可见性的影响比Volatile变量本身更重要。

 

并发编程的特性?

原子性,可见性,有序性

 

当线程A首先写入一个Volatile变量并且线程B随后读取该变量时,在写入Volatile变量之前对A可见的所有变量的值,在B读取了Volatile变量之后,对B也都是可见的。因此,写入Volatile变量相当于退出同步块,读取Volatile变量相当于进入同步块。但是,并不建议过度依赖Volatile变量提供的可见性,因为Volatile变量比使用锁的代码更加脆弱,也更难理解,仅当volatile变量能简化代码的实现以及对同步策略的验证时,才使用。

 

volatile变量通常用作某个操作完成,发生中断的标志。使用时要小心,因为volatile变量的语义不足以保证递增操作的原子性。加锁机制既可以确保可见性又可以确保原子性,而volatile只能保证可见性。

变量的递增例如i++实际上是三个操作,所以不是线程安全的,因为i++其实等同于i=i+1,首先读取i的值,然后对i的值加1,再把该值赋值给i。所以如果在这个过程中有另外的线程操作了i,那么就会出现内存不可见性问题导致操作不生效。

 

那么为什么volatile也不能保证递增是线程安全的呢?

因为volatile不能保证原子性,假如有个volatile变量1,两个想成分别对该变量执行5000次i++操作,那么有可能会出现这种情况,某一次两个线程都读取i值,由于i++是三步,i=i+1其实可以理解为m=i+1   i=m这两步,volatile确实保证了可见性,第一个线程读取volatile值时i=1,后面的就不能保证了,这个时候另一个线程也来读取给volatile值了,读取的时候也发现该变量值为1,两边都去进行第二步也就是i+1,然后将值赋值给i。此时对第一个线程来说i=i+1,i的值为2,然后对第二个线程,i=i+1,虽然左边的i值为2了,但是右边的i+1的值也为2,所以最终结果就是i=2而不是i=3,比如看下面的实例:

虽然大多数结果是10000,但是终究会出现其他的结果

 

 

那么我们什么时候该使用volatile呢?

1.对变量的写入操作不依赖变量的当前值(也就是i++操作不使用)

2.该变量不会与其他状态变量一起纳入不变性条件中

3.在访问变量时不需要加锁(读操作)

 

接下来看一下volatile的实现原理吧

被volatile修饰的变量会多出一条指令,Lock前缀指令,该指令有两个效果

1)将当前处理器缓存行的数据写回到系统内存

2)这个写回内存的操作会使其他cpu里缓存了该内存地址的数据无效(也就是其他处理器对应的缓存失效)

 

为了提高处理速度,处理器不会直接与内存进行通信,而是先将系统内存的数据读取到内部缓存,然后处理器进行修改后也是先保存在本地缓存中,最后再从本地缓存写回到系统内存。为了保证各个处理器缓存的值是一致的,实现了缓存一致性协议。假如其他处理器发现自己缓存的是过期的值,就会直接抛弃掉,当再要使用该值时,重新从系统内存中读取。

 

volatile在多级Cache中是如何实现的?

   靠的缓存一致性协议实现的,当cpu写数据时,如果发现操作的变量是共享变量,那么在对该变量进行写入的时候,会使其他cpu将该变量的缓存设置为无效状态,当其他cpu需要读取变量时,再重新从内存中去读取

 

参考书籍:《Java并发编程的艺术》 《Java并发编程实战》     (这两本书特别是第二本简直神了,建议先读第一本,再读第二本,哈哈哈哈哈)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值